1f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org/*
2f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *
4f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
5f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
6f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
7f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
8f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org */
10f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
11f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/asyncinvoker.h"
12f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/asyncudpsocket.h"
13f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/event.h"
14f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/gunit.h"
15f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/physicalsocketserver.h"
16f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/socketaddress.h"
17f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/thread.h"
18f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
19f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#if defined(WEBRTC_WIN)
20f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include <comdef.h>  // NOLINT
21f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#endif
22f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
23f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgusing namespace rtc;
24f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
25f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Generates a sequence of numbers (collaboratively).
26f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgclass TestGenerator {
27f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org public:
28f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  TestGenerator() : last(0), count(0) {}
29f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
30f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int Next(int prev) {
31f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    int result = prev + last;
32f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    last = result;
33f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    count += 1;
34f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return result;
35f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
36f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
37f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int last;
38f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int count;
39f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org};
40f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
41f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstruct TestMessage : public MessageData {
42f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  explicit TestMessage(int v) : value(v) {}
43f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  virtual ~TestMessage() {}
44f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
45f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int value;
46f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org};
47f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
48f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Receives on a socket and sends by posting messages.
49f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgclass SocketClient : public TestGenerator, public sigslot::has_slots<> {
50f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org public:
51f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  SocketClient(AsyncSocket* socket, const SocketAddress& addr,
52f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org               Thread* post_thread, MessageHandler* phandler)
53f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      : socket_(AsyncUDPSocket::Create(socket, addr)),
54f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        post_thread_(post_thread),
55f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        post_handler_(phandler) {
56f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    socket_->SignalReadPacket.connect(this, &SocketClient::OnPacket);
57f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
58f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
59f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  ~SocketClient() {
60f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    delete socket_;
61f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
62f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
63f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  SocketAddress address() const { return socket_->GetLocalAddress(); }
64f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
65f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  void OnPacket(AsyncPacketSocket* socket, const char* buf, size_t size,
66f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                const SocketAddress& remote_addr,
67f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                const PacketTime& packet_time) {
680c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    EXPECT_EQ(size, sizeof(uint32_t));
690c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint32_t prev = reinterpret_cast<const uint32_t*>(buf)[0];
700c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint32_t result = Next(prev);
71f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
72f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    post_thread_->PostDelayed(200, post_handler_, 0, new TestMessage(result));
73f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
74f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
75f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org private:
76f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  AsyncUDPSocket* socket_;
77f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Thread* post_thread_;
78f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  MessageHandler* post_handler_;
79f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org};
80f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
81f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Receives messages and sends on a socket.
82f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgclass MessageClient : public MessageHandler, public TestGenerator {
83f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org public:
84f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  MessageClient(Thread* pth, Socket* socket)
85f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      : socket_(socket) {
86f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
87f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
88f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  virtual ~MessageClient() {
89f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    delete socket_;
90f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
91f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
92f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  virtual void OnMessage(Message *pmsg) {
93f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    TestMessage* msg = static_cast<TestMessage*>(pmsg->pdata);
94f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    int result = Next(msg->value);
95f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    EXPECT_GE(socket_->Send(&result, sizeof(result)), 0);
96f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    delete msg;
97f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
98f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
99f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org private:
100f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Socket* socket_;
101f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org};
102f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
103f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgclass CustomThread : public rtc::Thread {
104f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org public:
105f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  CustomThread() {}
106f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  virtual ~CustomThread() { Stop(); }
107f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  bool Start() { return false; }
108ba737cba1aa6607911b1ca10460423b4c3e51fb9jiayl@webrtc.org
109ba737cba1aa6607911b1ca10460423b4c3e51fb9jiayl@webrtc.org  bool WrapCurrent() {
110ba737cba1aa6607911b1ca10460423b4c3e51fb9jiayl@webrtc.org    return Thread::WrapCurrent();
111ba737cba1aa6607911b1ca10460423b4c3e51fb9jiayl@webrtc.org  }
112ba737cba1aa6607911b1ca10460423b4c3e51fb9jiayl@webrtc.org  void UnwrapCurrent() {
113ba737cba1aa6607911b1ca10460423b4c3e51fb9jiayl@webrtc.org    Thread::UnwrapCurrent();
114ba737cba1aa6607911b1ca10460423b4c3e51fb9jiayl@webrtc.org  }
115f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org};
116f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
117f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
118f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// A thread that does nothing when it runs and signals an event
119f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// when it is destroyed.
120f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgclass SignalWhenDestroyedThread : public Thread {
121f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org public:
122f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  SignalWhenDestroyedThread(Event* event)
123f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      : event_(event) {
124f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
125f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
126f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  virtual ~SignalWhenDestroyedThread() {
127f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    Stop();
128f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    event_->Set();
129f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
130f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
131f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  virtual void Run() {
132f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // Do nothing.
133f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
134f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
135f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org private:
136f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Event* event_;
137f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org};
138f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
139d9b75bef5d0749ea94b31cedab0105c241938954nisse// A bool wrapped in a mutex, to avoid data races. Using a volatile
140d9b75bef5d0749ea94b31cedab0105c241938954nisse// bool should be sufficient for correct code ("eventual consistency"
141d9b75bef5d0749ea94b31cedab0105c241938954nisse// between caches is sufficient), but we can't tell the compiler about
142d9b75bef5d0749ea94b31cedab0105c241938954nisse// that, and then tsan complains about a data race.
143d9b75bef5d0749ea94b31cedab0105c241938954nisse
144d9b75bef5d0749ea94b31cedab0105c241938954nisse// See also discussion at
145d9b75bef5d0749ea94b31cedab0105c241938954nisse// http://stackoverflow.com/questions/7223164/is-mutex-needed-to-synchronize-a-simple-flag-between-pthreads
146d9b75bef5d0749ea94b31cedab0105c241938954nisse
147d9b75bef5d0749ea94b31cedab0105c241938954nisse// Using std::atomic<bool> or std::atomic_flag in C++11 is probably
148d9b75bef5d0749ea94b31cedab0105c241938954nisse// the right thing to do, but those features are not yet allowed. Or
149d9b75bef5d0749ea94b31cedab0105c241938954nisse// rtc::AtomicInt, if/when that is added. Since the use isn't
150d9b75bef5d0749ea94b31cedab0105c241938954nisse// performance critical, use a plain critical section for the time
151d9b75bef5d0749ea94b31cedab0105c241938954nisse// being.
152d9b75bef5d0749ea94b31cedab0105c241938954nisse
153d9b75bef5d0749ea94b31cedab0105c241938954nisseclass AtomicBool {
154d9b75bef5d0749ea94b31cedab0105c241938954nisse public:
155d9b75bef5d0749ea94b31cedab0105c241938954nisse  explicit AtomicBool(bool value = false) : flag_(value) {}
156d9b75bef5d0749ea94b31cedab0105c241938954nisse  AtomicBool& operator=(bool value) {
157d9b75bef5d0749ea94b31cedab0105c241938954nisse    CritScope scoped_lock(&cs_);
158d9b75bef5d0749ea94b31cedab0105c241938954nisse    flag_ = value;
159d9b75bef5d0749ea94b31cedab0105c241938954nisse    return *this;
160d9b75bef5d0749ea94b31cedab0105c241938954nisse  }
161d9b75bef5d0749ea94b31cedab0105c241938954nisse  bool get() const {
162d9b75bef5d0749ea94b31cedab0105c241938954nisse    CritScope scoped_lock(&cs_);
163d9b75bef5d0749ea94b31cedab0105c241938954nisse    return flag_;
164d9b75bef5d0749ea94b31cedab0105c241938954nisse  }
165d9b75bef5d0749ea94b31cedab0105c241938954nisse
166d9b75bef5d0749ea94b31cedab0105c241938954nisse private:
167d9b75bef5d0749ea94b31cedab0105c241938954nisse  mutable CriticalSection cs_;
168d9b75bef5d0749ea94b31cedab0105c241938954nisse  bool flag_;
169d9b75bef5d0749ea94b31cedab0105c241938954nisse};
170d9b75bef5d0749ea94b31cedab0105c241938954nisse
171f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Function objects to test Thread::Invoke.
172f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstruct FunctorA {
173f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int operator()() { return 42; }
174f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org};
175f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgclass FunctorB {
176f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org public:
177d9b75bef5d0749ea94b31cedab0105c241938954nisse  explicit FunctorB(AtomicBool* flag) : flag_(flag) {}
178f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  void operator()() { if (flag_) *flag_ = true; }
179f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org private:
180d9b75bef5d0749ea94b31cedab0105c241938954nisse  AtomicBool* flag_;
181f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org};
182f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstruct FunctorC {
183f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int operator()() {
184f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    Thread::Current()->ProcessMessages(50);
185f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return 24;
186f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
187f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org};
188f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
189f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// See: https://code.google.com/p/webrtc/issues/detail?id=2409
190f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgTEST(ThreadTest, DISABLED_Main) {
191f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  const SocketAddress addr("127.0.0.1", 0);
192f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
193f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Create the messaging client on its own thread.
194f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Thread th1;
195f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Socket* socket = th1.socketserver()->CreateAsyncSocket(addr.family(),
196f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                                         SOCK_DGRAM);
197f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  MessageClient msg_client(&th1, socket);
198f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
199f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Create the socket client on its own thread.
200f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Thread th2;
201f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  AsyncSocket* asocket =
202f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      th2.socketserver()->CreateAsyncSocket(addr.family(), SOCK_DGRAM);
203f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  SocketClient sock_client(asocket, addr, &th1, &msg_client);
204f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
205f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  socket->Connect(sock_client.address());
206f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
207f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  th1.Start();
208f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  th2.Start();
209f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
210f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Get the messages started.
211f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  th1.PostDelayed(100, &msg_client, 0, new TestMessage(1));
212f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
213f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Give the clients a little while to run.
214f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Messages will be processed at 100, 300, 500, 700, 900.
215f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Thread* th_main = Thread::Current();
216f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  th_main->ProcessMessages(1000);
217f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
218f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Stop the sending client. Give the receiver a bit longer to run, in case
219f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // it is running on a machine that is under load (e.g. the build machine).
220f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  th1.Stop();
221f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  th_main->ProcessMessages(200);
222f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  th2.Stop();
223f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
224f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Make sure the results were correct
225f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_EQ(5, msg_client.count);
226f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_EQ(34, msg_client.last);
227f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_EQ(5, sock_client.count);
228f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_EQ(55, sock_client.last);
229f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
230f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
231f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Test that setting thread names doesn't cause a malfunction.
232f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// There's no easy way to verify the name was set properly at this time.
233c732a3e5113bd64c85eeefa7a2ed3a5076e3db87henrike@webrtc.orgTEST(ThreadTest, Names) {
234f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Default name
235f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Thread *thread;
236f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  thread = new Thread();
237f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_TRUE(thread->Start());
238f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  thread->Stop();
239f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  delete thread;
240f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  thread = new Thread();
241f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Name with no object parameter
242f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_TRUE(thread->SetName("No object", NULL));
243f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_TRUE(thread->Start());
244f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  thread->Stop();
245f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  delete thread;
246f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Really long name
247f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  thread = new Thread();
248f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_TRUE(thread->SetName("Abcdefghijklmnopqrstuvwxyz1234567890", this));
249f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_TRUE(thread->Start());
250f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  thread->Stop();
251f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  delete thread;
252f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
253f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
254e30dab77dfaf4a156b50c899246c3734152d11b2henrike@webrtc.orgTEST(ThreadTest, Wrap) {
255e30dab77dfaf4a156b50c899246c3734152d11b2henrike@webrtc.org  Thread* current_thread = Thread::Current();
256e30dab77dfaf4a156b50c899246c3734152d11b2henrike@webrtc.org  current_thread->UnwrapCurrent();
257f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  CustomThread* cthread = new CustomThread();
258f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_TRUE(cthread->WrapCurrent());
259e5063b173303e9ee6c2246d2aa42a1480902b867fischman@webrtc.org  EXPECT_TRUE(cthread->RunningForTest());
260f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_FALSE(cthread->IsOwned());
261f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  cthread->UnwrapCurrent();
262e5063b173303e9ee6c2246d2aa42a1480902b867fischman@webrtc.org  EXPECT_FALSE(cthread->RunningForTest());
263f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  delete cthread;
264e30dab77dfaf4a156b50c899246c3734152d11b2henrike@webrtc.org  current_thread->WrapCurrent();
265f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
266f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
267c732a3e5113bd64c85eeefa7a2ed3a5076e3db87henrike@webrtc.orgTEST(ThreadTest, Invoke) {
268f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Create and start the thread.
269f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Thread thread;
270f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  thread.Start();
271f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Try calling functors.
272f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_EQ(42, thread.Invoke<int>(FunctorA()));
273d9b75bef5d0749ea94b31cedab0105c241938954nisse  AtomicBool called;
274f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  FunctorB f2(&called);
275f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  thread.Invoke<void>(f2);
276d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_TRUE(called.get());
277f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Try calling bare functions.
278f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  struct LocalFuncs {
279f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    static int Func1() { return 999; }
280f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    static void Func2() {}
281f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  };
282f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_EQ(999, thread.Invoke<int>(&LocalFuncs::Func1));
283f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  thread.Invoke<void>(&LocalFuncs::Func2);
284f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
285f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
2863987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org// Verifies that two threads calling Invoke on each other at the same time does
2873987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org// not deadlock.
2883987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.orgTEST(ThreadTest, TwoThreadsInvokeNoDeadlock) {
2893987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  AutoThread thread;
2903987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  Thread* current_thread = Thread::Current();
2913987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  ASSERT_TRUE(current_thread != NULL);
2923987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org
2933987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  Thread other_thread;
2943987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  other_thread.Start();
2953987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org
2963987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  struct LocalFuncs {
2973987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org    static void Set(bool* out) { *out = true; }
2983987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org    static void InvokeSet(Thread* thread, bool* out) {
2993987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org      thread->Invoke<void>(Bind(&Set, out));
3003987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org    }
3013987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  };
3023987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org
3033987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  bool called = false;
3043987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  other_thread.Invoke<void>(
3053987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org      Bind(&LocalFuncs::InvokeSet, current_thread, &called));
3063987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org
3073987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  EXPECT_TRUE(called);
3083987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org}
3093987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org
3103987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org// Verifies that if thread A invokes a call on thread B and thread C is trying
3113987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org// to invoke A at the same time, thread A does not handle C's invoke while
3123987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org// invoking B.
3133987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.orgTEST(ThreadTest, ThreeThreadsInvoke) {
3143987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  AutoThread thread;
3153987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  Thread* thread_a = Thread::Current();
3163987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  Thread thread_b, thread_c;
3173987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  thread_b.Start();
3183987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  thread_c.Start();
3193987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org
320e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org  class LockedBool {
321e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org   public:
322e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org    explicit LockedBool(bool value) : value_(value) {}
323e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org
324e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org    void Set(bool value) {
325e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org      CritScope lock(&crit_);
326e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org      value_ = value;
327e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org    }
328e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org
329e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org    bool Get() {
330e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org      CritScope lock(&crit_);
331e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org      return value_;
332e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org    }
333e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org
334e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org   private:
335e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org    CriticalSection crit_;
336e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org    bool value_ GUARDED_BY(crit_);
337e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org  };
338e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org
3393987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  struct LocalFuncs {
340e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org    static void Set(LockedBool* out) { out->Set(true); }
341e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org    static void InvokeSet(Thread* thread, LockedBool* out) {
3423987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org      thread->Invoke<void>(Bind(&Set, out));
3433987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org    }
3443987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org
3453987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org    // Set |out| true and call InvokeSet on |thread|.
346e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org    static void SetAndInvokeSet(LockedBool* out,
347e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org                                Thread* thread,
348e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org                                LockedBool* out_inner) {
349e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org      out->Set(true);
3503987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org      InvokeSet(thread, out_inner);
3513987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org    }
3523987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org
3533987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org    // Asynchronously invoke SetAndInvokeSet on |thread1| and wait until
3543987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org    // |thread1| starts the call.
3553987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org    static void AsyncInvokeSetAndWait(
356e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org        Thread* thread1, Thread* thread2, LockedBool* out) {
357e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org      CriticalSection crit;
358e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org      LockedBool async_invoked(false);
3593987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org
3603987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org      AsyncInvoker invoker;
3613987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org      invoker.AsyncInvoke<void>(
3623987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org          thread1, Bind(&SetAndInvokeSet, &async_invoked, thread2, out));
3633987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org
364e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org      EXPECT_TRUE_WAIT(async_invoked.Get(), 2000);
3653987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org    }
3663987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  };
3673987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org
368e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org  LockedBool thread_a_called(false);
3693987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org
3703987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  // Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A.
3713987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  // Thread B returns when C receives the call and C should be blocked until A
3723987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  // starts to process messages.
3733987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org  thread_b.Invoke<void>(Bind(&LocalFuncs::AsyncInvokeSetAndWait,
3743987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org                             &thread_c, thread_a, &thread_a_called));
375e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org  EXPECT_FALSE(thread_a_called.Get());
3763987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org
377e93cbd13d51c59763476528bb2232903504f7457pbos@webrtc.org  EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000);
3783987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org}
3793987b6de506a7e72a5bdfdf8c8ad9964705c5a28jiayl@webrtc.org
380f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgclass AsyncInvokeTest : public testing::Test {
381f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org public:
382f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  void IntCallback(int value) {
383f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    EXPECT_EQ(expected_thread_, Thread::Current());
384f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    int_value_ = value;
385f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
386f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  void AsyncInvokeIntCallback(AsyncInvoker* invoker, Thread* thread) {
387f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    expected_thread_ = thread;
388f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    invoker->AsyncInvoke(thread, FunctorC(),
389f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                         &AsyncInvokeTest::IntCallback,
390f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                         static_cast<AsyncInvokeTest*>(this));
391f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    invoke_started_.Set();
392f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
393f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  void SetExpectedThreadForIntCallback(Thread* thread) {
394f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    expected_thread_ = thread;
395f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
396f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
397f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org protected:
398f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  enum { kWaitTimeout = 1000 };
399f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  AsyncInvokeTest()
400f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      : int_value_(0),
401f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        invoke_started_(true, false),
402f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        expected_thread_(NULL) {}
403f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
404f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int int_value_;
405f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Event invoke_started_;
406f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Thread* expected_thread_;
407f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org};
408f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
409e30dab77dfaf4a156b50c899246c3734152d11b2henrike@webrtc.orgTEST_F(AsyncInvokeTest, FireAndForget) {
410f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  AsyncInvoker invoker;
411f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Create and start the thread.
412f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Thread thread;
413f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  thread.Start();
414f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Try calling functor.
415d9b75bef5d0749ea94b31cedab0105c241938954nisse  AtomicBool called;
416f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  invoker.AsyncInvoke<void>(&thread, FunctorB(&called));
417d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
418f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
419f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
420c732a3e5113bd64c85eeefa7a2ed3a5076e3db87henrike@webrtc.orgTEST_F(AsyncInvokeTest, WithCallback) {
421f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  AsyncInvoker invoker;
422f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Create and start the thread.
423f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Thread thread;
424f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  thread.Start();
425f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Try calling functor.
426f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  SetExpectedThreadForIntCallback(Thread::Current());
427f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  invoker.AsyncInvoke(&thread, FunctorA(),
428f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                      &AsyncInvokeTest::IntCallback,
429f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                      static_cast<AsyncInvokeTest*>(this));
430f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_EQ_WAIT(42, int_value_, kWaitTimeout);
431f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
432f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
433c732a3e5113bd64c85eeefa7a2ed3a5076e3db87henrike@webrtc.orgTEST_F(AsyncInvokeTest, CancelInvoker) {
434f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Create and start the thread.
435f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Thread thread;
436f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  thread.Start();
437f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Try destroying invoker during call.
438f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  {
439f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    AsyncInvoker invoker;
440f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    invoker.AsyncInvoke(&thread, FunctorC(),
441f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                        &AsyncInvokeTest::IntCallback,
442f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                        static_cast<AsyncInvokeTest*>(this));
443f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
444f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // With invoker gone, callback should be cancelled.
445f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Thread::Current()->ProcessMessages(kWaitTimeout);
446f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_EQ(0, int_value_);
447f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
448f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
449c732a3e5113bd64c85eeefa7a2ed3a5076e3db87henrike@webrtc.orgTEST_F(AsyncInvokeTest, CancelCallingThread) {
450f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  AsyncInvoker invoker;
451f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  { // Create and start the thread.
452f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    Thread thread;
453f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    thread.Start();
454f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // Try calling functor.
455f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    thread.Invoke<void>(Bind(&AsyncInvokeTest::AsyncInvokeIntCallback,
456f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                             static_cast<AsyncInvokeTest*>(this),
457f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                             &invoker, Thread::Current()));
458f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // Wait for the call to begin.
459f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
460f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
461f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Calling thread is gone. Return message shouldn't happen.
462f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Thread::Current()->ProcessMessages(kWaitTimeout);
463f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_EQ(0, int_value_);
464f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
465f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
466c732a3e5113bd64c85eeefa7a2ed3a5076e3db87henrike@webrtc.orgTEST_F(AsyncInvokeTest, KillInvokerBeforeExecute) {
467f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Thread thread;
468f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  thread.Start();
469f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  {
470f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    AsyncInvoker invoker;
471f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // Try calling functor.
472f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    thread.Invoke<void>(Bind(&AsyncInvokeTest::AsyncInvokeIntCallback,
473f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                             static_cast<AsyncInvokeTest*>(this),
474f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                             &invoker, Thread::Current()));
475f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // Wait for the call to begin.
476f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
477f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
478f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Invoker is destroyed. Function should not execute.
479f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Thread::Current()->ProcessMessages(kWaitTimeout);
480f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_EQ(0, int_value_);
481f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
482f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
483c732a3e5113bd64c85eeefa7a2ed3a5076e3db87henrike@webrtc.orgTEST_F(AsyncInvokeTest, Flush) {
484f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  AsyncInvoker invoker;
485d9b75bef5d0749ea94b31cedab0105c241938954nisse  AtomicBool flag1;
486d9b75bef5d0749ea94b31cedab0105c241938954nisse  AtomicBool flag2;
487f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Queue two async calls to the current thread.
488f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  invoker.AsyncInvoke<void>(Thread::Current(),
489f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                            FunctorB(&flag1));
490f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  invoker.AsyncInvoke<void>(Thread::Current(),
491f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                            FunctorB(&flag2));
492f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Because we haven't pumped messages, these should not have run yet.
493d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_FALSE(flag1.get());
494d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_FALSE(flag2.get());
495f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Force them to run now.
496f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  invoker.Flush(Thread::Current());
497d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_TRUE(flag1.get());
498d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_TRUE(flag2.get());
499f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
500f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
501c732a3e5113bd64c85eeefa7a2ed3a5076e3db87henrike@webrtc.orgTEST_F(AsyncInvokeTest, FlushWithIds) {
502f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  AsyncInvoker invoker;
503d9b75bef5d0749ea94b31cedab0105c241938954nisse  AtomicBool flag1;
504d9b75bef5d0749ea94b31cedab0105c241938954nisse  AtomicBool flag2;
505f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Queue two async calls to the current thread, one with a message id.
506f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  invoker.AsyncInvoke<void>(Thread::Current(),
507f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                            FunctorB(&flag1),
508f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                            5);
509f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  invoker.AsyncInvoke<void>(Thread::Current(),
510f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                            FunctorB(&flag2));
511f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Because we haven't pumped messages, these should not have run yet.
512d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_FALSE(flag1.get());
513d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_FALSE(flag2.get());
514f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Execute pending calls with id == 5.
515f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  invoker.Flush(Thread::Current(), 5);
516d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_TRUE(flag1.get());
517d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_FALSE(flag2.get());
518f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  flag1 = false;
519f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Execute all pending calls. The id == 5 call should not execute again.
520f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  invoker.Flush(Thread::Current());
521d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_FALSE(flag1.get());
522d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_TRUE(flag2.get());
523f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
524f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
525a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvertclass GuardedAsyncInvokeTest : public testing::Test {
526a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert public:
527a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  void IntCallback(int value) {
528a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    EXPECT_EQ(expected_thread_, Thread::Current());
529a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    int_value_ = value;
530a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  }
531a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  void AsyncInvokeIntCallback(GuardedAsyncInvoker* invoker, Thread* thread) {
532a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    expected_thread_ = thread;
533a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    invoker->AsyncInvoke(FunctorC(), &GuardedAsyncInvokeTest::IntCallback,
534a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert                         static_cast<GuardedAsyncInvokeTest*>(this));
535a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    invoke_started_.Set();
536a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  }
537a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  void SetExpectedThreadForIntCallback(Thread* thread) {
538a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    expected_thread_ = thread;
539a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  }
540a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert
541a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert protected:
542a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  const static int kWaitTimeout = 1000;
543a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  GuardedAsyncInvokeTest()
544a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert      : int_value_(0),
545a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert        invoke_started_(true, false),
546a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert        expected_thread_(nullptr) {}
547a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert
548a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  int int_value_;
549a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  Event invoke_started_;
550a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  Thread* expected_thread_;
551a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert};
552a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert
553a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert// Functor for creating an invoker.
554a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvertstruct CreateInvoker {
555a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  CreateInvoker(scoped_ptr<GuardedAsyncInvoker>* invoker) : invoker_(invoker) {}
556a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  void operator()() { invoker_->reset(new GuardedAsyncInvoker()); }
557a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  scoped_ptr<GuardedAsyncInvoker>* invoker_;
558a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert};
559a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert
560a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert// Test that we can call AsyncInvoke<void>() after the thread died.
561a1f590f3b6d317047d28b6568d1229973bb93f29Magnus JedvertTEST_F(GuardedAsyncInvokeTest, KillThreadFireAndForget) {
562a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Create and start the thread.
563a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  scoped_ptr<Thread> thread(new Thread());
564a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  thread->Start();
565a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  scoped_ptr<GuardedAsyncInvoker> invoker;
566a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Create the invoker on |thread|.
567a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  thread->Invoke<void>(CreateInvoker(&invoker));
568a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Kill |thread|.
569a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  thread = nullptr;
570a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Try calling functor.
571d9b75bef5d0749ea94b31cedab0105c241938954nisse  AtomicBool called;
572a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_FALSE(invoker->AsyncInvoke<void>(FunctorB(&called)));
573a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // With thread gone, nothing should happen.
574d9b75bef5d0749ea94b31cedab0105c241938954nisse  WAIT(called.get(), kWaitTimeout);
575d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_FALSE(called.get());
576a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert}
577a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert
578a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert// Test that we can call AsyncInvoke with callback after the thread died.
579a1f590f3b6d317047d28b6568d1229973bb93f29Magnus JedvertTEST_F(GuardedAsyncInvokeTest, KillThreadWithCallback) {
580a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Create and start the thread.
581a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  scoped_ptr<Thread> thread(new Thread());
582a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  thread->Start();
583a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  scoped_ptr<GuardedAsyncInvoker> invoker;
584a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Create the invoker on |thread|.
585a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  thread->Invoke<void>(CreateInvoker(&invoker));
586a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Kill |thread|.
587a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  thread = nullptr;
588a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Try calling functor.
589a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_FALSE(
590a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert      invoker->AsyncInvoke(FunctorC(), &GuardedAsyncInvokeTest::IntCallback,
591a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert                           static_cast<GuardedAsyncInvokeTest*>(this)));
592a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // With thread gone, callback should be cancelled.
593a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  Thread::Current()->ProcessMessages(kWaitTimeout);
594a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_EQ(0, int_value_);
595a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert}
596a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert
597a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert// The remaining tests check that GuardedAsyncInvoker behaves as AsyncInvoker
598a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert// when Thread is still alive.
599a1f590f3b6d317047d28b6568d1229973bb93f29Magnus JedvertTEST_F(GuardedAsyncInvokeTest, FireAndForget) {
600a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  GuardedAsyncInvoker invoker;
601a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Try calling functor.
602d9b75bef5d0749ea94b31cedab0105c241938954nisse  AtomicBool called;
603a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&called)));
604d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
605a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert}
606a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert
607a1f590f3b6d317047d28b6568d1229973bb93f29Magnus JedvertTEST_F(GuardedAsyncInvokeTest, WithCallback) {
608a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  GuardedAsyncInvoker invoker;
609a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Try calling functor.
610a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  SetExpectedThreadForIntCallback(Thread::Current());
611a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_TRUE(invoker.AsyncInvoke(FunctorA(),
612a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert                                  &GuardedAsyncInvokeTest::IntCallback,
613a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert                                  static_cast<GuardedAsyncInvokeTest*>(this)));
614a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_EQ_WAIT(42, int_value_, kWaitTimeout);
615a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert}
616a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert
617a1f590f3b6d317047d28b6568d1229973bb93f29Magnus JedvertTEST_F(GuardedAsyncInvokeTest, CancelInvoker) {
618a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Try destroying invoker during call.
619a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  {
620a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    GuardedAsyncInvoker invoker;
621a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    EXPECT_TRUE(
622a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert        invoker.AsyncInvoke(FunctorC(), &GuardedAsyncInvokeTest::IntCallback,
623a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert                            static_cast<GuardedAsyncInvokeTest*>(this)));
624a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  }
625a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // With invoker gone, callback should be cancelled.
626a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  Thread::Current()->ProcessMessages(kWaitTimeout);
627a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_EQ(0, int_value_);
628a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert}
629a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert
630a1f590f3b6d317047d28b6568d1229973bb93f29Magnus JedvertTEST_F(GuardedAsyncInvokeTest, CancelCallingThread) {
631a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  GuardedAsyncInvoker invoker;
632a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Try destroying calling thread during call.
633a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  {
634a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    Thread thread;
635a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    thread.Start();
636a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    // Try calling functor.
637a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    thread.Invoke<void>(Bind(&GuardedAsyncInvokeTest::AsyncInvokeIntCallback,
638a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert                             static_cast<GuardedAsyncInvokeTest*>(this),
639a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert                             &invoker, Thread::Current()));
640a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    // Wait for the call to begin.
641a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
642a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  }
643a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Calling thread is gone. Return message shouldn't happen.
644a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  Thread::Current()->ProcessMessages(kWaitTimeout);
645a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_EQ(0, int_value_);
646a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert}
647a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert
648a1f590f3b6d317047d28b6568d1229973bb93f29Magnus JedvertTEST_F(GuardedAsyncInvokeTest, KillInvokerBeforeExecute) {
649a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  Thread thread;
650a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  thread.Start();
651a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  {
652a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    GuardedAsyncInvoker invoker;
653a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    // Try calling functor.
654a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    thread.Invoke<void>(Bind(&GuardedAsyncInvokeTest::AsyncInvokeIntCallback,
655a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert                             static_cast<GuardedAsyncInvokeTest*>(this),
656a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert                             &invoker, Thread::Current()));
657a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    // Wait for the call to begin.
658a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert    ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
659a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  }
660a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Invoker is destroyed. Function should not execute.
661a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  Thread::Current()->ProcessMessages(kWaitTimeout);
662a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_EQ(0, int_value_);
663a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert}
664a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert
665a1f590f3b6d317047d28b6568d1229973bb93f29Magnus JedvertTEST_F(GuardedAsyncInvokeTest, Flush) {
666a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  GuardedAsyncInvoker invoker;
667d9b75bef5d0749ea94b31cedab0105c241938954nisse  AtomicBool flag1;
668d9b75bef5d0749ea94b31cedab0105c241938954nisse  AtomicBool flag2;
669a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Queue two async calls to the current thread.
670a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag1)));
671a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag2)));
672a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Because we haven't pumped messages, these should not have run yet.
673d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_FALSE(flag1.get());
674d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_FALSE(flag2.get());
675a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Force them to run now.
676a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_TRUE(invoker.Flush());
677d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_TRUE(flag1.get());
678d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_TRUE(flag2.get());
679a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert}
680a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert
681a1f590f3b6d317047d28b6568d1229973bb93f29Magnus JedvertTEST_F(GuardedAsyncInvokeTest, FlushWithIds) {
682a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  GuardedAsyncInvoker invoker;
683d9b75bef5d0749ea94b31cedab0105c241938954nisse  AtomicBool flag1;
684d9b75bef5d0749ea94b31cedab0105c241938954nisse  AtomicBool flag2;
685a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Queue two async calls to the current thread, one with a message id.
686a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag1), 5));
687a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag2)));
688a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Because we haven't pumped messages, these should not have run yet.
689d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_FALSE(flag1.get());
690d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_FALSE(flag2.get());
691a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Execute pending calls with id == 5.
692a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_TRUE(invoker.Flush(5));
693d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_TRUE(flag1.get());
694d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_FALSE(flag2.get());
695a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  flag1 = false;
696a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  // Execute all pending calls. The id == 5 call should not execute again.
697a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert  EXPECT_TRUE(invoker.Flush());
698d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_FALSE(flag1.get());
699d9b75bef5d0749ea94b31cedab0105c241938954nisse  EXPECT_TRUE(flag2.get());
700a1f590f3b6d317047d28b6568d1229973bb93f29Magnus Jedvert}
701f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
702f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#if defined(WEBRTC_WIN)
703f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgclass ComThreadTest : public testing::Test, public MessageHandler {
704f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org public:
705f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  ComThreadTest() : done_(false) {}
706f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org protected:
707f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  virtual void OnMessage(Message* message) {
708f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
709f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // S_FALSE means the thread was already inited for a multithread apartment.
710f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    EXPECT_EQ(S_FALSE, hr);
711f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (SUCCEEDED(hr)) {
712f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      CoUninitialize();
713f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
714f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    done_ = true;
715f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
716f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  bool done_;
717f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org};
718f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
719f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgTEST_F(ComThreadTest, ComInited) {
720f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Thread* thread = new ComThread();
721f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_TRUE(thread->Start());
722f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  thread->Post(this, 0);
723f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  EXPECT_TRUE_WAIT(done_, 1000);
724f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  delete thread;
725f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
726f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#endif
727