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