15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sync_channel.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
15a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/process_handle.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/run_loop.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_listener.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sender.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sync_message_filter.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sync_message_unittest.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::WaitableEvent;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace IPC {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Base class for a "process" with listener and IPC threads.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Worker : public Listener, public Sender {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Will create a channel without a name.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Worker(Channel::Mode mode, const std::string& thread_name)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : done_(new WaitableEvent(false, false)),
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        channel_created_(new WaitableEvent(false, false)),
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mode_(mode),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ipc_thread_((thread_name + "_ipc").c_str()),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        listener_thread_((thread_name + "_listener").c_str()),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        overrided_thread_(NULL),
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        shutdown_event_(true, false),
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        is_shutdown_(false) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Will create a named channel and use this name for the threads' name.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Worker(const std::string& channel_name, Channel::Mode mode)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : done_(new WaitableEvent(false, false)),
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        channel_created_(new WaitableEvent(false, false)),
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        channel_name_(channel_name),
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mode_(mode),
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ipc_thread_((channel_name + "_ipc").c_str()),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        listener_thread_((channel_name + "_listener").c_str()),
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        overrided_thread_(NULL),
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        shutdown_event_(true, false),
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        is_shutdown_(false) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~Worker() {
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Shutdown() must be called before destruction.
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK(is_shutdown_);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddRef() { }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Release() { }
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool Send(Message* msg) OVERRIDE { return channel_->Send(msg); }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForChannelCreation() { channel_created_->Wait(); }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CloseChannel() {
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(base::MessageLoop::current() == ListenerThread()->message_loop());
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_->Close();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Start() {
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StartThread(&listener_thread_, base::MessageLoop::TYPE_DEFAULT);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ListenerThread()->message_loop()->PostTask(
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Worker::OnStart, this));
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Shutdown() {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The IPC thread needs to outlive SyncChannel. We can't do this in
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // ~Worker(), since that'll reset the vtable pointer (to Worker's), which
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // may result in a race conditions. See http://crbug.com/25841.
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WaitableEvent listener_done(false, false), ipc_done(false, false);
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ListenerThread()->message_loop()->PostTask(
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE, base::Bind(&Worker::OnListenerThreadShutdown1, this,
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              &listener_done, &ipc_done));
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    listener_done.Wait();
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ipc_done.Wait();
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ipc_thread_.Stop();
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    listener_thread_.Stop();
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    is_shutdown_ = true;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OverrideThread(base::Thread* overrided_thread) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(overrided_thread_ == NULL);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    overrided_thread_ = overrided_thread;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  bool SendAnswerToLife(bool pump, bool succeed) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int answer = 0;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pump)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      msg->EnableMessagePumping();
1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    bool result = Send(msg);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(result, succeed);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(answer, (succeed ? 42 : 0));
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SendDouble(bool pump, bool succeed) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int answer = 0;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncMessage* msg = new SyncChannelTestMsg_Double(5, &answer);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pump)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      msg->EnableMessagePumping();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool result = Send(msg);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(result, succeed);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(answer, (succeed ? 10 : 0));
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& channel_name() { return channel_name_; }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Channel::Mode mode() { return mode_; }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* done_event() { return done_.get(); }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* shutdown_event() { return &shutdown_event_; }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ResetChannel() { channel_.reset(); }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Derived classes need to call this when they've completed their part of
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the test.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Done() { done_->Signal(); }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncChannel* channel() { return channel_.get(); }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Functions for dervied classes to implement if they wish.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Run() { }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnAnswer(int* answer) { NOTREACHED(); }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnAnswerDelay(Message* reply_msg) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The message handler map below can only take one entry for
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SyncChannelTestMsg_AnswerToLife, so since some classes want
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the normal version while other want the delayed reply, we
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // call the normal version if the derived class didn't override
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this function.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int answer;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnAnswer(&answer);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, answer);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply_msg);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnDouble(int in, int* out) { NOTREACHED(); }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnDoubleDelay(int in, Message* reply_msg) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnDouble(in, &result);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, result);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply_msg);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnNestedTestMsg(Message* reply_msg) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual SyncChannel* CreateChannel() {
15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<SyncChannel> channel = SyncChannel::Create(
15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        channel_name_, mode_, this, ipc_thread_.message_loop_proxy().get(),
15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        true, &shutdown_event_);
15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return channel.release();
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread* ListenerThread() {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return overrided_thread_ ? overrided_thread_ : &listener_thread_;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::Thread& ipc_thread() const { return ipc_thread_; }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the listener thread to create the sync channel.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnStart() {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Link ipc_thread_, listener_thread_ and channel_ altogether.
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StartThread(&ipc_thread_, base::MessageLoop::TYPE_IO);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_.reset(CreateChannel());
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_created_->Signal();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Run();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnListenerThreadShutdown1(WaitableEvent* listener_event,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 WaitableEvent* ipc_event) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SyncChannel needs to be destructed on the thread that it was created on.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_.reset();
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop().RunUntilIdle();
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ipc_thread_.message_loop()->PostTask(
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Worker::OnIPCThreadShutdown, this,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              listener_event, ipc_event));
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnIPCThreadShutdown(WaitableEvent* listener_event,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           WaitableEvent* ipc_event) {
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop().RunUntilIdle();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ipc_event->Signal();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listener_thread_.message_loop()->PostTask(
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Worker::OnListenerThreadShutdown2, this,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              listener_event));
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnListenerThreadShutdown2(WaitableEvent* listener_event) {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop().RunUntilIdle();
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listener_event->Signal();
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(Worker, message)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_Double, OnDoubleDelay)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_AnswerToLife,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     OnAnswerDelay)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelNestedTestMsg_String,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     OnNestedTestMsg)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StartThread(base::Thread* thread, base::MessageLoop::Type type) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Thread::Options options;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options.message_loop_type = type;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    thread->StartWithOptions(options);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WaitableEvent> done_;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WaitableEvent> channel_created_;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string channel_name_;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Channel::Mode mode_;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SyncChannel> channel_;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread ipc_thread_;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread listener_thread_;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread* overrided_thread_;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent shutdown_event_;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_shutdown_;
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Worker);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Starts the test with the given workers.  This function deletes the workers
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// when it's done.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RunTest(std::vector<Worker*> workers) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First we create the workers that are channel servers, or else the other
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // workers' channel initialization might fail because the pipe isn't created..
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < workers.size(); ++i) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (workers[i]->mode() & Channel::MODE_SERVER_FLAG) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      workers[i]->Start();
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      workers[i]->WaitForChannelCreation();
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // now create the clients
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < workers.size(); ++i) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (workers[i]->mode() & Channel::MODE_CLIENT_FLAG)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      workers[i]->Start();
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // wait for all the workers to finish
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < workers.size(); ++i)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    workers[i]->done_event()->Wait();
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < workers.size(); ++i) {
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    workers[i]->Shutdown();
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete workers[i];
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IPCSyncChannelTest : public testing::Test {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop message_loop_;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SimpleServer : public Worker {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit SimpleServer(bool pump_during_send)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_SERVER, "simpler_server"),
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pump_during_send_(pump_during_send) { }
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    SendAnswerToLife(pump_during_send_, true);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SimpleClient : public Worker {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimpleClient() : Worker(Channel::MODE_CLIENT, "simple_client") { }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswer(int* answer) OVERRIDE {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *answer = 42;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Simple(bool pump_during_send) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new SimpleServer(pump_during_send));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new SimpleClient());
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests basic synchronous call
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, Simple) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Simple(false);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Simple(true);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Worker classes which override how the sync channel is created to use the
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// two-step initialization (calling the lightweight constructor and then
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ChannelProxy::Init separately) process.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TwoStepServer : public Worker {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit TwoStepServer(bool create_pipe_now)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_SERVER, "simpler_server"),
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        create_pipe_now_(create_pipe_now) { }
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
3200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    SendAnswerToLife(false, true);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual SyncChannel* CreateChannel() OVERRIDE {
32546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    SyncChannel* channel =
32646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        SyncChannel::Create(channel_name(), mode(), this,
32746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            ipc_thread().message_loop_proxy().get(),
32846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            create_pipe_now_,
32946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            shutdown_event()).release();
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return channel;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool create_pipe_now_;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TwoStepClient : public Worker {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TwoStepClient(bool create_pipe_now)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_CLIENT, "simple_client"),
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        create_pipe_now_(create_pipe_now) { }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswer(int* answer) OVERRIDE {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *answer = 42;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual SyncChannel* CreateChannel() OVERRIDE {
34846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    SyncChannel* channel =
34946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        SyncChannel::Create(channel_name(), mode(), this,
35046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            ipc_thread().message_loop_proxy().get(),
35146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            create_pipe_now_,
35246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            shutdown_event()).release();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return channel;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool create_pipe_now_;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TwoStep(bool create_server_pipe_now, bool create_client_pipe_now) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new TwoStepServer(create_server_pipe_now));
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new TwoStepClient(create_client_pipe_now));
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests basic two-step initialization, where you call the lightweight
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// constructor then Init.
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, TwoStepInitialization) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TwoStep(false, false);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TwoStep(false, true);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TwoStep(true, false);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TwoStep(true, true);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DelayClient : public Worker {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayClient() : Worker(Channel::MODE_CLIENT, "delay_client") { }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswerDelay(Message* reply_msg) OVERRIDE {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply_msg);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DelayReply(bool pump_during_send) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new SimpleServer(pump_during_send));
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new DelayClient());
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that asynchronous replies work
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, DelayReply) {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayReply(false);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayReply(true);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NoHangServer : public Worker {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NoHangServer(WaitableEvent* got_first_reply, bool pump_during_send)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_SERVER, "no_hang_server"),
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        got_first_reply_(got_first_reply),
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pump_during_send_(pump_during_send) { }
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
4100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    SendAnswerToLife(pump_during_send_, true);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    got_first_reply_->Signal();
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    SendAnswerToLife(pump_during_send_, false);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* got_first_reply_;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NoHangClient : public Worker {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit NoHangClient(WaitableEvent* got_first_reply)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Worker(Channel::MODE_CLIENT, "no_hang_client"),
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      got_first_reply_(got_first_reply) { }
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswerDelay(Message* reply_msg) OVERRIDE {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Use the DELAY_REPLY macro so that we can force the reply to be sent
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // before this function returns (when the channel will be reset).
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply_msg);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    got_first_reply_->Wait();
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseChannel();
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* got_first_reply_;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NoHang(bool pump_during_send) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent got_first_reply(false, false);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new NoHangServer(&got_first_reply, pump_during_send));
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new NoHangClient(&got_first_reply));
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that caller doesn't hang if receiver dies
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, NoHang) {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NoHang(false);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NoHang(true);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UnblockServer : public Worker {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnblockServer(bool pump_during_send, bool delete_during_send)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Worker(Channel::MODE_SERVER, "unblock_server"),
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pump_during_send_(pump_during_send),
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete_during_send_(delete_during_send) { }
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delete_during_send_) {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Use custom code since race conditions mean the answer may or may not be
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // available.
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int answer = 0;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (pump_during_send_)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        msg->EnableMessagePumping();
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Send(msg);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      SendAnswerToLife(pump_during_send_, true);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnDoubleDelay(int in, Message* reply_msg) OVERRIDE {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, in * 2);
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply_msg);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delete_during_send_)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ResetChannel();
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool delete_during_send_;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UnblockClient : public Worker {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit UnblockClient(bool pump_during_send)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Worker(Channel::MODE_CLIENT, "unblock_client"),
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pump_during_send_(pump_during_send) { }
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswer(int* answer) OVERRIDE {
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendDouble(pump_during_send_, true);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *answer = 42;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Unblock(bool server_pump, bool client_pump, bool delete_during_send) {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new UnblockServer(server_pump, delete_during_send));
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new UnblockClient(client_pump));
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that the caller unblocks to answer a sync message from the receiver.
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, Unblock) {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(false, false, false);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(false, true, false);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(true, false, false);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(true, true, false);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that the the SyncChannel object can be deleted during a Send.
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, ChannelDeleteDuringSend) {
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(false, false, true);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(false, true, true);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(true, false, true);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(true, true, true);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RecursiveServer : public Worker {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveServer(bool expected_send_result, bool pump_first, bool pump_second)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_SERVER, "recursive_server"),
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expected_send_result_(expected_send_result),
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pump_first_(pump_first), pump_second_(pump_second) {}
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendDouble(pump_first_, expected_send_result_);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnDouble(int in, int* out) OVERRIDE {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *out = in * 2;
5430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    SendAnswerToLife(pump_second_, expected_send_result_);
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool expected_send_result_, pump_first_, pump_second_;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RecursiveClient : public Worker {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveClient(bool pump_during_send, bool close_channel)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_CLIENT, "recursive_client"),
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pump_during_send_(pump_during_send), close_channel_(close_channel) {}
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnDoubleDelay(int in, Message* reply_msg) OVERRIDE {
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendDouble(pump_during_send_, !close_channel_);
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (close_channel_) {
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete reply_msg;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, in * 2);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Send(reply_msg);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswerDelay(Message* reply_msg) OVERRIDE {
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (close_channel_) {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete reply_msg;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CloseChannel();
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Send(reply_msg);
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_, close_channel_;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Recursive(
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool server_pump_first, bool server_pump_second, bool client_pump) {
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new RecursiveServer(true, server_pump_first, server_pump_second));
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new RecursiveClient(client_pump, false));
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests a server calling Send while another Send is pending.
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, Recursive) {
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(false, false, false);
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(false, false, true);
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(false, true, false);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(false, true, true);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(true, false, false);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(true, false, true);
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(true, true, false);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(true, true, true);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RecursiveNoHang(
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool server_pump_first, bool server_pump_second, bool client_pump) {
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new RecursiveServer(false, server_pump_first, server_pump_second));
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new RecursiveClient(client_pump, true));
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that if a caller makes a sync call during an existing sync call and
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the receiver dies, neither of the Send() calls hang.
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, RecursiveNoHang) {
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(false, false, false);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(false, false, true);
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(false, true, false);
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(false, true, true);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(true, false, false);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(true, false, true);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(true, true, false);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(true, true, true);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MultipleServer1 : public Worker {
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit MultipleServer1(bool pump_during_send)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Worker("test_channel1", Channel::MODE_SERVER),
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pump_during_send_(pump_during_send) { }
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendDouble(pump_during_send_, true);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MultipleClient1 : public Worker {
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MultipleClient1(WaitableEvent* client1_msg_received,
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  WaitableEvent* client1_can_reply) :
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Worker("test_channel1", Channel::MODE_CLIENT),
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client1_msg_received_(client1_msg_received),
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client1_can_reply_(client1_can_reply) { }
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnDouble(int in, int* out) OVERRIDE {
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client1_msg_received_->Signal();
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *out = in * 2;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client1_can_reply_->Wait();
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent *client1_msg_received_, *client1_can_reply_;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MultipleServer2 : public Worker {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MultipleServer2() : Worker("test_channel2", Channel::MODE_SERVER) { }
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswer(int* result) OVERRIDE {
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *result = 42;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MultipleClient2 : public Worker {
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MultipleClient2(
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WaitableEvent* client1_msg_received, WaitableEvent* client1_can_reply,
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool pump_during_send)
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Worker("test_channel2", Channel::MODE_CLIENT),
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client1_msg_received_(client1_msg_received),
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client1_can_reply_(client1_can_reply),
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pump_during_send_(pump_during_send) { }
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client1_msg_received_->Wait();
6810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    SendAnswerToLife(pump_during_send_, true);
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client1_can_reply_->Signal();
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent *client1_msg_received_, *client1_can_reply_;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Multiple(bool server_pump, bool client_pump) {
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A shared worker thread so that server1 and server2 run on one thread.
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread worker_thread("Multiple");
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(worker_thread.Start());
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Server1 sends a sync msg to client1, which blocks the reply until
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // server2 (which runs on the same worker thread as server1) responds
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to a sync msg from client2.
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent client1_msg_received(false, false);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent client1_can_reply(false, false);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Worker* worker;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new MultipleServer2();
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker->OverrideThread(&worker_thread);
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new MultipleClient2(
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &client1_msg_received, &client1_can_reply, client_pump);
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new MultipleServer1(server_pump);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker->OverrideThread(&worker_thread);
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new MultipleClient1(
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &client1_msg_received, &client1_can_reply);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that multiple SyncObjects on the same listener thread can unblock each
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// other.
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, Multiple) {
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Multiple(false, false);
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Multiple(false, true);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Multiple(true, false);
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Multiple(true, true);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class provides server side functionality to test the case where
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// multiple sync channels are in use on the same thread on the client and
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// nested calls are issued.
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class QueuedReplyServer : public Worker {
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QueuedReplyServer(base::Thread* listener_thread,
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& channel_name,
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& reply_text)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(channel_name, Channel::MODE_SERVER),
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reply_text_(reply_text) {
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Worker::OverrideThread(listener_thread);
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnNestedTestMsg(Message* reply_msg) OVERRIDE {
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << __FUNCTION__ << " Sending reply: " << reply_text_;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelNestedTestMsg_String::WriteReplyParams(reply_msg, reply_text_);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply_msg);
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string reply_text_;
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The QueuedReplyClient class provides functionality to test the case where
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// multiple sync channels are in use on the same thread and they make nested
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sync calls, i.e. while the first channel waits for a response it makes a
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sync call on another channel.
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The callstack should unwind correctly, i.e. the outermost call should
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// complete first, and so on.
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class QueuedReplyClient : public Worker {
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QueuedReplyClient(base::Thread* listener_thread,
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& channel_name,
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& expected_text,
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    bool pump_during_send)
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(channel_name, Channel::MODE_CLIENT),
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pump_during_send_(pump_during_send),
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expected_text_(expected_text) {
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Worker::OverrideThread(listener_thread);
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string response;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncMessage* msg = new SyncChannelNestedTestMsg_String(&response);
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pump_during_send_)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      msg->EnableMessagePumping();
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool result = Send(msg);
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(result);
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(response, expected_text_);
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << __FUNCTION__ << " Received reply: " << response;
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_;
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string expected_text_;
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QueuedReply(bool client_pump) {
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A shared worker thread for servers
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread server_worker_thread("QueuedReply_ServerListener");
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(server_worker_thread.Start());
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread client_worker_thread("QueuedReply_ClientListener");
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(client_worker_thread.Start());
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Worker* worker;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new QueuedReplyServer(&server_worker_thread,
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "QueuedReply_Server1",
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "Got first message");
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new QueuedReplyServer(&server_worker_thread,
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "QueuedReply_Server2",
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "Got second message");
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new QueuedReplyClient(&client_worker_thread,
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "QueuedReply_Server1",
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "Got first message",
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 client_pump);
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new QueuedReplyClient(&client_worker_thread,
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "QueuedReply_Server2",
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "Got second message",
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 client_pump);
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// While a blocking send is in progress, the listener thread might answer other
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// synchronous messages.  This tests that if during the response to another
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// message the reply to the original messages comes, it is queued up correctly
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and the original Send is unblocked later.
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We also test that the send call stacks unwind correctly when the channel
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pumps messages while waiting for a response.
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, QueuedReply) {
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QueuedReply(false);
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QueuedReply(true);
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChattyClient : public Worker {
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChattyClient() :
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Worker(Channel::MODE_CLIENT, "chatty_client") { }
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswer(int* answer) OVERRIDE {
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The PostMessage limit is 10k.  Send 20% more than that.
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kMessageLimit = 10000;
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kMessagesToSend = kMessageLimit * 120 / 100;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kMessagesToSend; ++i) {
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!SendDouble(false, true))
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *answer = 42;
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChattyServer(bool pump_during_send) {
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new UnblockServer(pump_during_send, false));
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new ChattyClient());
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests http://b/1093251 - that sending lots of sync messages while
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the receiver is waiting for a sync reply does not overflow the PostMessage
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// queue.
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, ChattyServer) {
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChattyServer(false);
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChattyServer(true);
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NestedCallback(Worker* server) {
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sleep a bit so that we wake up after the reply has been received.
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(250));
8840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  server->SendAnswerToLife(true, true);
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool timeout_occurred = false;
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TimeoutCallback() {
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_occurred = true;
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DoneEventRaceServer : public Worker {
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoneEventRaceServer()
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_SERVER, "done_event_race_server") { }
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
899c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->PostTask(FROM_HERE,
900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           base::Bind(&NestedCallback, this));
901c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&TimeoutCallback),
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromSeconds(9));
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Even though we have a timeout on the Send, it will succeed since for this
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // bug, the reply message comes back and is deserialized, however the done
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // event wasn't set.  So we indirectly use the timeout task to notice if a
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // timeout occurred.
9090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    SendAnswerToLife(true, true);
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!timeout_occurred);
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests http://b/1474092 - that if after the done_event is set but before
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OnObjectSignaled is called another message is sent out, then after its
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// reply comes back OnObjectSignaled will be called for the first message.
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, DoneEventRace) {
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new DoneEventRaceServer());
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new SimpleClient());
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestSyncMessageFilter : public SyncMessageFilter {
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSyncMessageFilter(base::WaitableEvent* shutdown_event,
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        Worker* worker,
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        scoped_refptr<base::MessageLoopProxy> message_loop)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : SyncMessageFilter(shutdown_event),
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        worker_(worker),
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        message_loop_(message_loop) {
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
937f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual void OnFilterAdded(Sender* sender) OVERRIDE {
938f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SyncMessageFilter::OnFilterAdded(sender);
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_->PostTask(
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&TestSyncMessageFilter::SendMessageOnHelperThread, this));
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SendMessageOnHelperThread() {
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int answer = 0;
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer));
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(result);
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(answer, 42);
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    worker_->Done();
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TestSyncMessageFilter() {}
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Worker* worker_;
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> message_loop_;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyncMessageFilterServer : public Worker {
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncMessageFilterServer()
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_SERVER, "sync_message_filter_server"),
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        thread_("helper_thread") {
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Thread::Options options;
966c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    thread_.StartWithOptions(options);
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filter_ = new TestSyncMessageFilter(shutdown_event(), this,
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        thread_.message_loop_proxy());
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel()->AddFilter(filter_.get());
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975