ipc_sync_channel_unittest.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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)
9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnFilterAdded(Channel* channel) OVERRIDE {
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncMessageFilter::OnFilterAdded(channel);
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)  }
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread thread_;
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<TestSyncMessageFilter> filter_;
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class provides functionality to test the case that a Send on the sync
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// channel does not crash after the channel has been closed.
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ServerSendAfterClose : public Worker {
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ServerSendAfterClose()
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     : Worker(Channel::MODE_SERVER, "simpler_server"),
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       send_result_(true) {
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SendDummy() {
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ListenerThread()->message_loop()->PostTask(
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(base::IgnoreResult(&ServerSendAfterClose::Send),
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              this, new SyncChannelTestMsg_NoArgs));
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool send_result() const {
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return send_result_;
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
10012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseChannel();
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool Send(Message* msg) OVERRIDE {
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    send_result_ = Worker::Send(msg);
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return send_result_;
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool send_result_;
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests basic synchronous call
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, SyncMessageFilter) {
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new SyncMessageFilterServer());
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new SimpleClient());
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test the case when the channel is closed and a Send is attempted after that.
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, SendAfterClose) {
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ServerSendAfterClose server;
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server.Start();
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server.done_event()->Wait();
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server.done_event()->Reset();
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server.SendDummy();
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server.done_event()->Wait();
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(server.send_result());
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  server.Shutdown();
10372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RestrictedDispatchServer : public Worker {
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchServer(WaitableEvent* sent_ping_event,
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           WaitableEvent* wait_event)
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("restricted_channel", Channel::MODE_SERVER),
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sent_ping_event_(sent_ping_event),
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        wait_event_(wait_event) { }
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDoPing(int ping) {
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send an asynchronous message that unblocks the caller.
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* msg = new SyncChannelTestMsg_Ping(ping);
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msg->set_unblock(true);
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(msg);
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Signal the event after the message has been sent on the channel, on the
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // IPC thread.
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ipc_thread().message_loop()->PostTask(
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&RestrictedDispatchServer::OnPingSent, this));
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnPingTTL(int ping, int* out) {
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *out = ping;
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wait_event_->Wait();
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread* ListenerThread() { return Worker::ListenerThread(); }
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
10682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchServer, message)
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_PingTTL, OnPingTTL)
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnPingSent() {
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sent_ping_event_->Signal();
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnNoArgs() { }
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* sent_ping_event_;
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* wait_event_;
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NonRestrictedDispatchServer : public Worker {
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NonRestrictedDispatchServer(WaitableEvent* signal_event)
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("non_restricted_channel", Channel::MODE_SERVER),
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        signal_event_(signal_event) {}
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread* ListenerThread() { return Worker::ListenerThread(); }
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDoPingTTL(int ping) {
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int value = 0;
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new SyncChannelTestMsg_PingTTL(ping, &value));
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    signal_event_->Signal();
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
11012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(NonRestrictedDispatchServer, message)
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnNoArgs() { }
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* signal_event_;
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RestrictedDispatchClient : public Worker {
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchClient(WaitableEvent* sent_ping_event,
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           RestrictedDispatchServer* server,
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           NonRestrictedDispatchServer* server2,
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int* success)
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("restricted_channel", Channel::MODE_CLIENT),
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ping_(0),
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_(server),
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server2_(server2),
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        success_(success),
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sent_ping_event_(sent_ping_event) {}
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Incoming messages from our channel should only be dispatched when we
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // send a message on that same channel.
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel()->SetRestrictDispatchChannelGroup(1);
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_->ListenerThread()->message_loop()->PostTask(
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&RestrictedDispatchServer::OnDoPing, server_, 1));
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sent_ping_event_->Wait();
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new SyncChannelTestMsg_NoArgs);
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ping_ == 1)
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++*success_;
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Send failed to dispatch incoming message on same channel";
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
114046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    non_restricted_channel_ =
114146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        SyncChannel::Create("non_restricted_channel",
114246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            IPC::Channel::MODE_CLIENT,
114346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            this,
114446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            ipc_thread().message_loop_proxy().get(),
114546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            true,
114646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            shutdown_event());
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_->ListenerThread()->message_loop()->PostTask(
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&RestrictedDispatchServer::OnDoPing, server_, 2));
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sent_ping_event_->Wait();
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check that the incoming message is *not* dispatched when sending on the
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // non restricted channel.
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(piman): there is a possibility of a false positive race condition
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // here, if the message that was posted on the server-side end of the pipe
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // is not visible yet on the client side, but I don't know how to solve this
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // without hooking into the internals of SyncChannel. I haven't seen it in
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // practice (i.e. not setting SetRestrictDispatchToSameChannel does cause
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the following to fail).
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    non_restricted_channel_->Send(new SyncChannelTestMsg_NoArgs);
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ping_ == 1)
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++*success_;
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Send dispatched message from restricted channel";
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new SyncChannelTestMsg_NoArgs);
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ping_ == 2)
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++*success_;
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Send failed to dispatch incoming message on same channel";
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check that the incoming message on the non-restricted channel is
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // dispatched when sending on the restricted channel.
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server2_->ListenerThread()->message_loop()->PostTask(
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&NonRestrictedDispatchServer::OnDoPingTTL, server2_, 3));
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int value = 0;
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new SyncChannelTestMsg_PingTTL(4, &value));
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ping_ == 3 && value == 4)
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++*success_;
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Send failed to dispatch message from unrestricted channel";
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    non_restricted_channel_->Send(new SyncChannelTestMsg_Done);
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    non_restricted_channel_.reset();
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new SyncChannelTestMsg_Done);
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
11902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchClient, message)
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Ping, OnPing)
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_PingTTL, OnPingTTL)
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnPing(int ping) {
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ping_ = ping;
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnPingTTL(int ping, IPC::Message* reply) {
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ping_ = ping;
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This message comes from the NonRestrictedDispatchServer, we have to send
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the reply back manually.
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelTestMsg_PingTTL::WriteReplyParams(reply, ping);
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    non_restricted_channel_->Send(reply);
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ping_;
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchServer* server_;
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NonRestrictedDispatchServer* server2_;
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int* success_;
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* sent_ping_event_;
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SyncChannel> non_restricted_channel_;
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, RestrictedDispatch) {
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent sent_ping_event(false, false);
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent wait_event(false, false);
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchServer* server =
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new RestrictedDispatchServer(&sent_ping_event, &wait_event);
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NonRestrictedDispatchServer* server2 =
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new NonRestrictedDispatchServer(&wait_event);
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int success = 0;
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(server);
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(server2);
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new RestrictedDispatchClient(
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &sent_ping_event, server, server2, &success));
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(4, success);
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test case inspired by crbug.com/108491
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We create two servers that use the same ListenerThread but have
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SetRestrictDispatchToSameChannel set to true.
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We create clients, then use some specific WaitableEvent wait/signalling to
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ensure that messages get dispatched in a way that causes a deadlock due to
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a nested dispatch and an eligible message in a higher-level dispatch's
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// delayed_queue. Specifically, we start with client1 about so send an
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// unblocking message to server1, while the shared listener thread for the
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// servers server1 and server2 is about to send a non-unblocking message to
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// client1. At the same time, client2 will be about to send an unblocking
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// message to server2. Server1 will handle the client1->server1 message by
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// telling server2 to send a non-unblocking message to client2.
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// What should happen is that the send to server2 should find the pending,
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// same-context client2->server2 message to dispatch, causing client2 to
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// unblock then handle the server2->client2 message, so that the shared
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// servers' listener thread can then respond to the client1->server1 message.
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Then client1 can handle the non-unblocking server1->client1 message.
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The old code would end up in a state where the server2->client2 message is
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sent, but the client2->server2 message (which is eligible for dispatch, and
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which is what client2 is waiting for) is stashed in a local delayed_queue
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that has server1's channel context, causing a deadlock.
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WaitableEvents in the events array are used to:
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   event 0: indicate to client1 that server listener is in OnDoServerTask
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   event 1: indicate to client1 that client2 listener is in OnDoClient2Task
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   event 2: indicate to server1 that client2 listener is in OnDoClient2Task
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   event 3: indicate to client2 that server listener is in OnDoServerTask
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RestrictedDispatchDeadlockServer : public Worker {
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockServer(int server_num,
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   WaitableEvent* server_ready_event,
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   WaitableEvent** events,
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   RestrictedDispatchDeadlockServer* peer)
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(server_num == 1 ? "channel1" : "channel2", Channel::MODE_SERVER),
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_num_(server_num),
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_ready_event_(server_ready_event),
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        events_(events),
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        peer_(peer) { }
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDoServerTask() {
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[3]->Signal();
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[2]->Wait();
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[0]->Signal();
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendMessageToClient();
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel()->SetRestrictDispatchChannelGroup(1);
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_ready_event_->Signal();
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread* ListenerThread() { return Worker::ListenerThread(); }
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
12922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockServer, message)
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnNoArgs() {
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (server_num_ == 1) {
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(peer_ != NULL);
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      peer_->SendMessageToClient();
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SendMessageToClient() {
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* msg = new SyncChannelTestMsg_NoArgs;
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msg->set_unblock(false);
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!msg->should_unblock());
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(msg);
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int server_num_;
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* server_ready_event_;
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent** events_;
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockServer* peer_;
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RestrictedDispatchDeadlockClient2 : public Worker {
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockClient2(RestrictedDispatchDeadlockServer* server,
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    WaitableEvent* server_ready_event,
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    WaitableEvent** events)
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("channel2", Channel::MODE_CLIENT),
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_ready_event_(server_ready_event),
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        events_(events),
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        received_msg_(false),
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        received_noarg_reply_(false),
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        done_issued_(false) {}
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_ready_event_->Wait();
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDoClient2Task() {
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[3]->Wait();
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[1]->Signal();
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[2]->Signal();
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(received_msg_ == false);
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* message = new SyncChannelTestMsg_NoArgs;
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message->set_unblock(true);
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(message);
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    received_noarg_reply_ = true;
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread* ListenerThread() { return Worker::ListenerThread(); }
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
13502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockClient2, message)
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnNoArgs() {
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    received_msg_ = true;
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PossiblyDone();
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PossiblyDone() {
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (received_noarg_reply_ && received_msg_) {
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(done_issued_ == false);
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      done_issued_ = true;
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Send(new SyncChannelTestMsg_Done);
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Done();
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* server_ready_event_;
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent** events_;
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool received_msg_;
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool received_noarg_reply_;
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool done_issued_;
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RestrictedDispatchDeadlockClient1 : public Worker {
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockClient1(RestrictedDispatchDeadlockServer* server,
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    RestrictedDispatchDeadlockClient2* peer,
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    WaitableEvent* server_ready_event,
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    WaitableEvent** events)
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("channel1", Channel::MODE_CLIENT),
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_(server),
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        peer_(peer),
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_ready_event_(server_ready_event),
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        events_(events),
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        received_msg_(false),
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        received_noarg_reply_(false),
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        done_issued_(false) {}
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_ready_event_->Wait();
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_->ListenerThread()->message_loop()->PostTask(
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&RestrictedDispatchDeadlockServer::OnDoServerTask, server_));
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    peer_->ListenerThread()->message_loop()->PostTask(
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&RestrictedDispatchDeadlockClient2::OnDoClient2Task, peer_));
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[0]->Wait();
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[1]->Wait();
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(received_msg_ == false);
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* message = new SyncChannelTestMsg_NoArgs;
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message->set_unblock(true);
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(message);
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    received_noarg_reply_ = true;
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PossiblyDone();
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
14132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockClient1, message)
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnNoArgs() {
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    received_msg_ = true;
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PossiblyDone();
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PossiblyDone() {
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (received_noarg_reply_ && received_msg_) {
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(done_issued_ == false);
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      done_issued_ = true;
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Send(new SyncChannelTestMsg_Done);
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Done();
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockServer* server_;
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockClient2* peer_;
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* server_ready_event_;
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent** events_;
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool received_msg_;
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool received_noarg_reply_;
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool done_issued_;
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, RestrictedDispatchDeadlock) {
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A shared worker thread so that server1 and server2 run on one thread.
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread worker_thread("RestrictedDispatchDeadlock");
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(worker_thread.Start());
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent server1_ready(false, false);
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent server2_ready(false, false);
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event0(false, false);
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event1(false, false);
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event2(false, false);
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event3(false, false);
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* events[4] = {&event0, &event1, &event2, &event3};
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockServer* server1;
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockServer* server2;
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockClient1* client1;
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockClient2* client2;
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server2 = new RestrictedDispatchDeadlockServer(2, &server2_ready, events,
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 NULL);
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server2->OverrideThread(&worker_thread);
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(server2);
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client2 = new RestrictedDispatchDeadlockClient2(server2, &server2_ready,
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  events);
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(client2);
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server1 = new RestrictedDispatchDeadlockServer(1, &server1_ready, events,
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 server2);
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server1->OverrideThread(&worker_thread);
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(server1);
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client1 = new RestrictedDispatchDeadlockClient1(server1, client2,
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  &server1_ready, events);
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(client1);
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test case inspired by crbug.com/120530
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We create 4 workers that pipe to each other W1->W2->W3->W4->W1 then we send a
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// message that recurses through 3, 4 or 5 steps to make sure, say, W1 can
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// re-enter when called from W4 while it's sending a message to W2.
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The first worker drives the whole test so it must be treated specially.
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RestrictedDispatchPipeWorker : public Worker {
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchPipeWorker(
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string &channel1,
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WaitableEvent* event1,
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string &channel2,
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WaitableEvent* event2,
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int group,
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int* success)
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(channel1, Channel::MODE_SERVER),
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        event1_(event1),
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        event2_(event2),
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        other_channel_name_(channel2),
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        group_(group),
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        success_(success) {
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnPingTTL(int ping, int* ret) {
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *ret = 0;
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ping)
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    other_channel_->Send(new SyncChannelTestMsg_PingTTL(ping - 1, ret));
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++*ret;
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDone() {
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_first())
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    other_channel_->Send(new SyncChannelTestMsg_Done);
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    other_channel_.reset();
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel()->SetRestrictDispatchChannelGroup(group_);
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_first())
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event1_->Signal();
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event2_->Wait();
153146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    other_channel_ =
153246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        SyncChannel::Create(other_channel_name_,
153346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            IPC::Channel::MODE_CLIENT,
153446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            this,
153546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            ipc_thread().message_loop_proxy().get(),
153646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            true,
153746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            shutdown_event());
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    other_channel_->SetRestrictDispatchChannelGroup(group_);
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!is_first()) {
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event1_->Signal();
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *success_ = 0;
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int value = 0;
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnPingTTL(3, &value);
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *success_ += (value == 3);
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnPingTTL(4, &value);
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *success_ += (value == 4);
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnPingTTL(5, &value);
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *success_ += (value == 5);
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    other_channel_->Send(new SyncChannelTestMsg_Done);
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    other_channel_.reset();
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_first() { return !!success_; }
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
15592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchPipeWorker, message)
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_PingTTL, OnPingTTL)
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, OnDone)
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SyncChannel> other_channel_;
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* event1_;
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* event2_;
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string other_channel_name_;
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int group_;
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int* success_;
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, RestrictedDispatch4WayDeadlock) {
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int success = 0;
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event0(true, false);
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event1(true, false);
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event2(true, false);
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event3(true, false);
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new RestrictedDispatchPipeWorker(
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "channel0", &event0, "channel1", &event1, 1, &success));
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new RestrictedDispatchPipeWorker(
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "channel1", &event1, "channel2", &event2, 2, NULL));
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new RestrictedDispatchPipeWorker(
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "channel2", &event2, "channel3", &event3, 3, NULL));
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new RestrictedDispatchPipeWorker(
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "channel3", &event3, "channel0", &event0, 4, NULL));
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3, success);
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test case inspired by crbug.com/122443
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We want to make sure a reply message with the unblock flag set correctly
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// behaves as a reply, not a regular message.
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We have 3 workers. Server1 will send a message to Server2 (which will block),
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// during which it will dispatch a message comming from Client, at which point
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it will send another message to Server2. While sending that second message it
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will receive a reply from Server1 with the unblock flag.
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ReentrantReplyServer1 : public Worker {
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReentrantReplyServer1(WaitableEvent* server_ready)
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("reentrant_reply1", Channel::MODE_SERVER),
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_ready_(server_ready) { }
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
161146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    server2_channel_ =
161246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        SyncChannel::Create("reentrant_reply2",
161346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            IPC::Channel::MODE_CLIENT,
161446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            this,
161546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            ipc_thread().message_loop_proxy().get(),
161646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            true,
161746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            shutdown_event());
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_ready_->Signal();
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* msg = new SyncChannelTestMsg_Reentrant1();
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server2_channel_->Send(msg);
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server2_channel_.reset();
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
16262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(ReentrantReplyServer1, message)
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Reentrant2, OnReentrant2)
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_REPLY_HANDLER(OnReply)
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnReentrant2() {
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* msg = new SyncChannelTestMsg_Reentrant3();
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server2_channel_->Send(msg);
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnReply(const Message& message) {
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we get here, the Send() will never receive the reply (thus would
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // hang), so abort instead.
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(FATAL) << "Reply message was dispatched";
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* server_ready_;
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SyncChannel> server2_channel_;
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ReentrantReplyServer2 : public Worker {
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReentrantReplyServer2()
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("reentrant_reply2", Channel::MODE_SERVER),
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reply_(NULL) { }
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
16562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(ReentrantReplyServer2, message)
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER_DELAY_REPLY(
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         SyncChannelTestMsg_Reentrant1, OnReentrant1)
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Reentrant3, OnReentrant3)
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnReentrant1(Message* reply) {
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!reply_);
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reply_ = reply;
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnReentrant3() {
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(reply_);
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* reply = reply_;
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reply_ = NULL;
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reply->set_unblock(true);
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply);
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Message* reply_;
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ReentrantReplyClient : public Worker {
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReentrantReplyClient(WaitableEvent* server_ready)
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("reentrant_reply1", Channel::MODE_CLIENT),
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_ready_(server_ready) { }
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_ready_->Wait();
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new SyncChannelTestMsg_Reentrant2());
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* server_ready_;
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, ReentrantReply) {
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent server_ready(false, false);
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new ReentrantReplyServer2());
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new ReentrantReplyServer1(&server_ready));
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new ReentrantReplyClient(&server_ready));
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generate a validated channel ID using Channel::GenerateVerifiedChannelID().
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VerifiedServer : public Worker {
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifiedServer(base::Thread* listener_thread,
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const std::string& channel_name,
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const std::string& reply_text)
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(channel_name, Channel::MODE_SERVER),
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reply_text_(reply_text) {
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Worker::OverrideThread(listener_thread);
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnNestedTestMsg(Message* reply_msg) OVERRIDE {
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << __FUNCTION__ << " Sending reply: " << reply_text_;
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelNestedTestMsg_String::WriteReplyParams(reply_msg, reply_text_);
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply_msg);
172546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ASSERT_EQ(channel()->GetPeerPID(), base::GetCurrentProcId());
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string reply_text_;
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VerifiedClient : public Worker {
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifiedClient(base::Thread* listener_thread,
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const std::string& channel_name,
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const std::string& expected_text)
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(channel_name, Channel::MODE_CLIENT),
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expected_text_(expected_text) {
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Worker::OverrideThread(listener_thread);
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string response;
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncMessage* msg = new SyncChannelNestedTestMsg_String(&response);
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool result = Send(msg);
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(result);
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(response, expected_text_);
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // expected_text_ is only used in the above DCHECK. This line suppresses the
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "unused private field" warning in release builds.
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void)expected_text_;
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << __FUNCTION__ << " Received reply: " << response;
175446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ASSERT_EQ(channel()->GetPeerPID(), base::GetCurrentProcId());
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string expected_text_;
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Verified() {
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A shared worker thread for servers
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread server_worker_thread("Verified_ServerListener");
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(server_worker_thread.Start());
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread client_worker_thread("Verified_ClientListener");
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(client_worker_thread.Start());
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string channel_id = Channel::GenerateVerifiedChannelID("Verified");
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Worker* worker;
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new VerifiedServer(&server_worker_thread,
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              channel_id,
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              "Got first message");
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new VerifiedClient(&client_worker_thread,
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              channel_id,
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              "Got first message");
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows needs to send an out-of-band secret to verify the client end of the
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// channel. Test that we still connect correctly in that case.
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, Verified) {
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Verified();
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace IPC
1796