ipc_sync_channel_unittest.cc revision 9ab5563a3196760eb381d102cbb2bc0f7abc6a50
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"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/process_util.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)  bool SendWithTimeout(Message* msg, int timeout_ms) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return channel_->SendWithTimeout(msg, timeout_ms);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForChannelCreation() { channel_created_->Wait(); }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CloseChannel() {
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(base::MessageLoop::current() == ListenerThread()->message_loop());
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_->Close();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Start() {
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StartThread(&listener_thread_, base::MessageLoop::TYPE_DEFAULT);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ListenerThread()->message_loop()->PostTask(
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Worker::OnStart, this));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Shutdown() {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The IPC thread needs to outlive SyncChannel. We can't do this in
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // ~Worker(), since that'll reset the vtable pointer (to Worker's), which
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // may result in a race conditions. See http://crbug.com/25841.
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WaitableEvent listener_done(false, false), ipc_done(false, false);
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ListenerThread()->message_loop()->PostTask(
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE, base::Bind(&Worker::OnListenerThreadShutdown1, this,
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              &listener_done, &ipc_done));
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    listener_done.Wait();
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ipc_done.Wait();
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ipc_thread_.Stop();
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    listener_thread_.Stop();
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    is_shutdown_ = true;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OverrideThread(base::Thread* overrided_thread) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(overrided_thread_ == NULL);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    overrided_thread_ = overrided_thread;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SendAnswerToLife(bool pump, int timeout, bool succeed) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int answer = 0;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pump)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      msg->EnableMessagePumping();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool result = SendWithTimeout(msg, timeout);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(result, succeed);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(answer, (succeed ? 42 : 0));
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SendDouble(bool pump, bool succeed) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int answer = 0;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncMessage* msg = new SyncChannelTestMsg_Double(5, &answer);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pump)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      msg->EnableMessagePumping();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool result = Send(msg);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(result, succeed);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(answer, (succeed ? 10 : 0));
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& channel_name() { return channel_name_; }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Channel::Mode mode() { return mode_; }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* done_event() { return done_.get(); }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* shutdown_event() { return &shutdown_event_; }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ResetChannel() { channel_.reset(); }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Derived classes need to call this when they've completed their part of
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the test.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Done() { done_->Signal(); }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncChannel* channel() { return channel_.get(); }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Functions for dervied classes to implement if they wish.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Run() { }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnAnswer(int* answer) { NOTREACHED(); }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnAnswerDelay(Message* reply_msg) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The message handler map below can only take one entry for
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SyncChannelTestMsg_AnswerToLife, so since some classes want
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the normal version while other want the delayed reply, we
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // call the normal version if the derived class didn't override
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this function.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int answer;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnAnswer(&answer);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, answer);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply_msg);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnDouble(int in, int* out) { NOTREACHED(); }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnDoubleDelay(int in, Message* reply_msg) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnDouble(in, &result);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, result);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply_msg);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnNestedTestMsg(Message* reply_msg) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual SyncChannel* CreateChannel() {
1577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return new SyncChannel(channel_name_,
1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                           mode_,
1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                           this,
1607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                           ipc_thread_.message_loop_proxy().get(),
1617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                           true,
1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                           &shutdown_event_);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread* ListenerThread() {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return overrided_thread_ ? overrided_thread_ : &listener_thread_;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::Thread& ipc_thread() const { return ipc_thread_; }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the listener thread to create the sync channel.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnStart() {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Link ipc_thread_, listener_thread_ and channel_ altogether.
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StartThread(&ipc_thread_, base::MessageLoop::TYPE_IO);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_.reset(CreateChannel());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_created_->Signal();
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Run();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnListenerThreadShutdown1(WaitableEvent* listener_event,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 WaitableEvent* ipc_event) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SyncChannel needs to be destructed on the thread that it was created on.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_.reset();
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop().RunUntilIdle();
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ipc_thread_.message_loop()->PostTask(
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Worker::OnIPCThreadShutdown, this,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              listener_event, ipc_event));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnIPCThreadShutdown(WaitableEvent* listener_event,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           WaitableEvent* ipc_event) {
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop().RunUntilIdle();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ipc_event->Signal();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listener_thread_.message_loop()->PostTask(
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&Worker::OnListenerThreadShutdown2, this,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              listener_event));
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnListenerThreadShutdown2(WaitableEvent* listener_event) {
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop().RunUntilIdle();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listener_event->Signal();
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(Worker, message)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_Double, OnDoubleDelay)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_AnswerToLife,
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     OnAnswerDelay)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelNestedTestMsg_String,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     OnNestedTestMsg)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StartThread(base::Thread* thread, base::MessageLoop::Type type) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Thread::Options options;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options.message_loop_type = type;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    thread->StartWithOptions(options);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WaitableEvent> done_;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WaitableEvent> channel_created_;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string channel_name_;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Channel::Mode mode_;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SyncChannel> channel_;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread ipc_thread_;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread listener_thread_;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread* overrided_thread_;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent shutdown_event_;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_shutdown_;
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Worker);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Starts the test with the given workers.  This function deletes the workers
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// when it's done.
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RunTest(std::vector<Worker*> workers) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First we create the workers that are channel servers, or else the other
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // workers' channel initialization might fail because the pipe isn't created..
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < workers.size(); ++i) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (workers[i]->mode() & Channel::MODE_SERVER_FLAG) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      workers[i]->Start();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      workers[i]->WaitForChannelCreation();
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // now create the clients
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < workers.size(); ++i) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (workers[i]->mode() & Channel::MODE_CLIENT_FLAG)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      workers[i]->Start();
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // wait for all the workers to finish
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < workers.size(); ++i)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    workers[i]->done_event()->Wait();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < workers.size(); ++i) {
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    workers[i]->Shutdown();
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete workers[i];
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IPCSyncChannelTest : public testing::Test {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop message_loop_;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SimpleServer : public Worker {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit SimpleServer(bool pump_during_send)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_SERVER, "simpler_server"),
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pump_during_send_(pump_during_send) { }
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendAnswerToLife(pump_during_send_, base::kNoTimeout, true);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SimpleClient : public Worker {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimpleClient() : Worker(Channel::MODE_CLIENT, "simple_client") { }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswer(int* answer) OVERRIDE {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *answer = 42;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Simple(bool pump_during_send) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new SimpleServer(pump_during_send));
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new SimpleClient());
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests basic synchronous call
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, Simple) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Simple(false);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Simple(true);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Worker classes which override how the sync channel is created to use the
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// two-step initialization (calling the lightweight constructor and then
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ChannelProxy::Init separately) process.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TwoStepServer : public Worker {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit TwoStepServer(bool create_pipe_now)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_SERVER, "simpler_server"),
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        create_pipe_now_(create_pipe_now) { }
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendAnswerToLife(false, base::kNoTimeout, true);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual SyncChannel* CreateChannel() OVERRIDE {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannel* channel = new SyncChannel(
3317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        this, ipc_thread().message_loop_proxy().get(), shutdown_event());
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel->Init(channel_name(), mode(), create_pipe_now_);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return channel;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool create_pipe_now_;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TwoStepClient : public Worker {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TwoStepClient(bool create_pipe_now)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_CLIENT, "simple_client"),
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        create_pipe_now_(create_pipe_now) { }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswer(int* answer) OVERRIDE {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *answer = 42;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual SyncChannel* CreateChannel() OVERRIDE {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannel* channel = new SyncChannel(
3527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        this, ipc_thread().message_loop_proxy().get(), shutdown_event());
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel->Init(channel_name(), mode(), create_pipe_now_);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return channel;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool create_pipe_now_;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TwoStep(bool create_server_pipe_now, bool create_client_pipe_now) {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new TwoStepServer(create_server_pipe_now));
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new TwoStepClient(create_client_pipe_now));
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests basic two-step initialization, where you call the lightweight
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// constructor then Init.
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, TwoStepInitialization) {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TwoStep(false, false);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TwoStep(false, true);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TwoStep(true, false);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TwoStep(true, true);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DelayClient : public Worker {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayClient() : Worker(Channel::MODE_CLIENT, "delay_client") { }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswerDelay(Message* reply_msg) OVERRIDE {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply_msg);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DelayReply(bool pump_during_send) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new SimpleServer(pump_during_send));
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new DelayClient());
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that asynchronous replies work
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, DelayReply) {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayReply(false);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayReply(true);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NoHangServer : public Worker {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NoHangServer(WaitableEvent* got_first_reply, bool pump_during_send)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_SERVER, "no_hang_server"),
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        got_first_reply_(got_first_reply),
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pump_during_send_(pump_during_send) { }
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendAnswerToLife(pump_during_send_, base::kNoTimeout, true);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    got_first_reply_->Signal();
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendAnswerToLife(pump_during_send_, base::kNoTimeout, false);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* got_first_reply_;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NoHangClient : public Worker {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit NoHangClient(WaitableEvent* got_first_reply)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Worker(Channel::MODE_CLIENT, "no_hang_client"),
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      got_first_reply_(got_first_reply) { }
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswerDelay(Message* reply_msg) OVERRIDE {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Use the DELAY_REPLY macro so that we can force the reply to be sent
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // before this function returns (when the channel will be reset).
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply_msg);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    got_first_reply_->Wait();
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseChannel();
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* got_first_reply_;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NoHang(bool pump_during_send) {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent got_first_reply(false, false);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new NoHangServer(&got_first_reply, pump_during_send));
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new NoHangClient(&got_first_reply));
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that caller doesn't hang if receiver dies
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, NoHang) {
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NoHang(false);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NoHang(true);
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UnblockServer : public Worker {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnblockServer(bool pump_during_send, bool delete_during_send)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Worker(Channel::MODE_SERVER, "unblock_server"),
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pump_during_send_(pump_during_send),
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete_during_send_(delete_during_send) { }
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delete_during_send_) {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Use custom code since race conditions mean the answer may or may not be
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // available.
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int answer = 0;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (pump_during_send_)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        msg->EnableMessagePumping();
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Send(msg);
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SendAnswerToLife(pump_during_send_, base::kNoTimeout, true);
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnDoubleDelay(int in, Message* reply_msg) OVERRIDE {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, in * 2);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply_msg);
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delete_during_send_)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ResetChannel();
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool delete_during_send_;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UnblockClient : public Worker {
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit UnblockClient(bool pump_during_send)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Worker(Channel::MODE_CLIENT, "unblock_client"),
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pump_during_send_(pump_during_send) { }
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswer(int* answer) OVERRIDE {
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendDouble(pump_during_send_, true);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *answer = 42;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Unblock(bool server_pump, bool client_pump, bool delete_during_send) {
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new UnblockServer(server_pump, delete_during_send));
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new UnblockClient(client_pump));
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that the caller unblocks to answer a sync message from the receiver.
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, Unblock) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(false, false, false);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(false, true, false);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(true, false, false);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(true, true, false);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that the the SyncChannel object can be deleted during a Send.
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, ChannelDeleteDuringSend) {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(false, false, true);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(false, true, true);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(true, false, true);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Unblock(true, true, true);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RecursiveServer : public Worker {
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveServer(bool expected_send_result, bool pump_first, bool pump_second)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_SERVER, "recursive_server"),
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expected_send_result_(expected_send_result),
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pump_first_(pump_first), pump_second_(pump_second) {}
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendDouble(pump_first_, expected_send_result_);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnDouble(int in, int* out) OVERRIDE {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *out = in * 2;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendAnswerToLife(pump_second_, base::kNoTimeout, expected_send_result_);
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool expected_send_result_, pump_first_, pump_second_;
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RecursiveClient : public Worker {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveClient(bool pump_during_send, bool close_channel)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_CLIENT, "recursive_client"),
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pump_during_send_(pump_during_send), close_channel_(close_channel) {}
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnDoubleDelay(int in, Message* reply_msg) OVERRIDE {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendDouble(pump_during_send_, !close_channel_);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (close_channel_) {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete reply_msg;
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, in * 2);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Send(reply_msg);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswerDelay(Message* reply_msg) OVERRIDE {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (close_channel_) {
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete reply_msg;
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CloseChannel();
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Send(reply_msg);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_, close_channel_;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Recursive(
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool server_pump_first, bool server_pump_second, bool client_pump) {
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new RecursiveServer(true, server_pump_first, server_pump_second));
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new RecursiveClient(client_pump, false));
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests a server calling Send while another Send is pending.
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, Recursive) {
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(false, false, false);
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(false, false, true);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(false, true, false);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(false, true, true);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(true, false, false);
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(true, false, true);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(true, true, false);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Recursive(true, true, true);
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RecursiveNoHang(
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool server_pump_first, bool server_pump_second, bool client_pump) {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new RecursiveServer(false, server_pump_first, server_pump_second));
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new RecursiveClient(client_pump, true));
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that if a caller makes a sync call during an existing sync call and
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the receiver dies, neither of the Send() calls hang.
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, RecursiveNoHang) {
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(false, false, false);
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(false, false, true);
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(false, true, false);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(false, true, true);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(true, false, false);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(true, false, true);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(true, true, false);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecursiveNoHang(true, true, true);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MultipleServer1 : public Worker {
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit MultipleServer1(bool pump_during_send)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Worker("test_channel1", Channel::MODE_SERVER),
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pump_during_send_(pump_during_send) { }
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendDouble(pump_during_send_, true);
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MultipleClient1 : public Worker {
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MultipleClient1(WaitableEvent* client1_msg_received,
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  WaitableEvent* client1_can_reply) :
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Worker("test_channel1", Channel::MODE_CLIENT),
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client1_msg_received_(client1_msg_received),
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client1_can_reply_(client1_can_reply) { }
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnDouble(int in, int* out) OVERRIDE {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client1_msg_received_->Signal();
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *out = in * 2;
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client1_can_reply_->Wait();
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent *client1_msg_received_, *client1_can_reply_;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MultipleServer2 : public Worker {
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MultipleServer2() : Worker("test_channel2", Channel::MODE_SERVER) { }
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswer(int* result) OVERRIDE {
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *result = 42;
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MultipleClient2 : public Worker {
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MultipleClient2(
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WaitableEvent* client1_msg_received, WaitableEvent* client1_can_reply,
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool pump_during_send)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Worker("test_channel2", Channel::MODE_CLIENT),
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client1_msg_received_(client1_msg_received),
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client1_can_reply_(client1_can_reply),
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pump_during_send_(pump_during_send) { }
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client1_msg_received_->Wait();
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendAnswerToLife(pump_during_send_, base::kNoTimeout, true);
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client1_can_reply_->Signal();
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent *client1_msg_received_, *client1_can_reply_;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_;
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Multiple(bool server_pump, bool client_pump) {
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A shared worker thread so that server1 and server2 run on one thread.
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread worker_thread("Multiple");
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(worker_thread.Start());
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Server1 sends a sync msg to client1, which blocks the reply until
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // server2 (which runs on the same worker thread as server1) responds
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to a sync msg from client2.
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent client1_msg_received(false, false);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent client1_can_reply(false, false);
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Worker* worker;
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new MultipleServer2();
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker->OverrideThread(&worker_thread);
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new MultipleClient2(
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &client1_msg_received, &client1_can_reply, client_pump);
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new MultipleServer1(server_pump);
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker->OverrideThread(&worker_thread);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new MultipleClient1(
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &client1_msg_received, &client1_can_reply);
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that multiple SyncObjects on the same listener thread can unblock each
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// other.
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, Multiple) {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Multiple(false, false);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Multiple(false, true);
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Multiple(true, false);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Multiple(true, true);
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class provides server side functionality to test the case where
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// multiple sync channels are in use on the same thread on the client and
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// nested calls are issued.
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class QueuedReplyServer : public Worker {
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QueuedReplyServer(base::Thread* listener_thread,
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& channel_name,
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& reply_text)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(channel_name, Channel::MODE_SERVER),
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reply_text_(reply_text) {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Worker::OverrideThread(listener_thread);
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnNestedTestMsg(Message* reply_msg) OVERRIDE {
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << __FUNCTION__ << " Sending reply: " << reply_text_;
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelNestedTestMsg_String::WriteReplyParams(reply_msg, reply_text_);
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply_msg);
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string reply_text_;
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The QueuedReplyClient class provides functionality to test the case where
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// multiple sync channels are in use on the same thread and they make nested
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sync calls, i.e. while the first channel waits for a response it makes a
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sync call on another channel.
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The callstack should unwind correctly, i.e. the outermost call should
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// complete first, and so on.
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class QueuedReplyClient : public Worker {
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QueuedReplyClient(base::Thread* listener_thread,
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& channel_name,
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& expected_text,
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    bool pump_during_send)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(channel_name, Channel::MODE_CLIENT),
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pump_during_send_(pump_during_send),
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expected_text_(expected_text) {
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Worker::OverrideThread(listener_thread);
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string response;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncMessage* msg = new SyncChannelNestedTestMsg_String(&response);
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pump_during_send_)
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      msg->EnableMessagePumping();
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool result = Send(msg);
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(result);
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(response, expected_text_);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << __FUNCTION__ << " Received reply: " << response;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_;
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string expected_text_;
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QueuedReply(bool client_pump) {
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A shared worker thread for servers
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread server_worker_thread("QueuedReply_ServerListener");
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(server_worker_thread.Start());
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread client_worker_thread("QueuedReply_ClientListener");
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(client_worker_thread.Start());
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Worker* worker;
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new QueuedReplyServer(&server_worker_thread,
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "QueuedReply_Server1",
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "Got first message");
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new QueuedReplyServer(&server_worker_thread,
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "QueuedReply_Server2",
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "Got second message");
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new QueuedReplyClient(&client_worker_thread,
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "QueuedReply_Server1",
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "Got first message",
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 client_pump);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new QueuedReplyClient(&client_worker_thread,
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "QueuedReply_Server2",
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "Got second message",
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 client_pump);
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// While a blocking send is in progress, the listener thread might answer other
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// synchronous messages.  This tests that if during the response to another
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// message the reply to the original messages comes, it is queued up correctly
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and the original Send is unblocked later.
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We also test that the send call stacks unwind correctly when the channel
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pumps messages while waiting for a response.
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, QueuedReply) {
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QueuedReply(false);
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QueuedReply(true);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChattyClient : public Worker {
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChattyClient() :
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Worker(Channel::MODE_CLIENT, "chatty_client") { }
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswer(int* answer) OVERRIDE {
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The PostMessage limit is 10k.  Send 20% more than that.
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kMessageLimit = 10000;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kMessagesToSend = kMessageLimit * 120 / 100;
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kMessagesToSend; ++i) {
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!SendDouble(false, true))
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *answer = 42;
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChattyServer(bool pump_during_send) {
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new UnblockServer(pump_during_send, false));
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new ChattyClient());
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests http://b/1093251 - that sending lots of sync messages while
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the receiver is waiting for a sync reply does not overflow the PostMessage
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// queue.
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, ChattyServer) {
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChattyServer(false);
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChattyServer(true);
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TimeoutServer : public Worker {
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeoutServer(int timeout_ms,
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                std::vector<bool> timeout_seq,
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                bool pump_during_send)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_SERVER, "timeout_server"),
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        timeout_ms_(timeout_ms),
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        timeout_seq_(timeout_seq),
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pump_during_send_(pump_during_send) {
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::vector<bool>::const_iterator iter = timeout_seq_.begin();
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         iter != timeout_seq_.end(); ++iter) {
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SendAnswerToLife(pump_during_send_, timeout_ms_, !*iter);
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int timeout_ms_;
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<bool> timeout_seq_;
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pump_during_send_;
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UnresponsiveClient : public Worker {
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit UnresponsiveClient(std::vector<bool> timeout_seq)
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_CLIENT, "unresponsive_client"),
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        timeout_seq_(timeout_seq) {
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAnswerDelay(Message* reply_msg) OVERRIDE {
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!timeout_seq_.empty());
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!timeout_seq_[0]) {
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Send(reply_msg);
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Don't reply.
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete reply_msg;
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    timeout_seq_.erase(timeout_seq_.begin());
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (timeout_seq_.empty())
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Done();
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether we should time-out or respond to the various messages we receive.
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<bool> timeout_seq_;
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SendWithTimeoutOK(bool pump_during_send) {
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<bool> timeout_seq;
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_seq.push_back(false);
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_seq.push_back(false);
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_seq.push_back(false);
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new TimeoutServer(5000, timeout_seq, pump_during_send));
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new SimpleClient());
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SendWithTimeoutTimeout(bool pump_during_send) {
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<bool> timeout_seq;
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_seq.push_back(true);
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_seq.push_back(false);
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_seq.push_back(false);
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new TimeoutServer(100, timeout_seq, pump_during_send));
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new UnresponsiveClient(timeout_seq));
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SendWithTimeoutMixedOKAndTimeout(bool pump_during_send) {
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<bool> timeout_seq;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_seq.push_back(true);
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_seq.push_back(false);
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_seq.push_back(false);
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_seq.push_back(true);
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_seq.push_back(false);
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new TimeoutServer(100, timeout_seq, pump_during_send));
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new UnresponsiveClient(timeout_seq));
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that SendWithTimeout does not time-out if the response comes back fast
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// enough.
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, SendWithTimeoutOK) {
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendWithTimeoutOK(false);
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendWithTimeoutOK(true);
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that SendWithTimeout does time-out.
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, SendWithTimeoutTimeout) {
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendWithTimeoutTimeout(false);
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendWithTimeoutTimeout(true);
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sends some message that time-out and some that succeed.
9822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(IPCSyncChannelTest, SendWithTimeoutMixedOKAndTimeout) {
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendWithTimeoutMixedOKAndTimeout(false);
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendWithTimeoutMixedOKAndTimeout(true);
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NestedCallback(Worker* server) {
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sleep a bit so that we wake up after the reply has been received.
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(250));
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server->SendAnswerToLife(true, base::kNoTimeout, true);
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool timeout_occurred = false;
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TimeoutCallback() {
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_occurred = true;
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DoneEventRaceServer : public Worker {
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoneEventRaceServer()
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_SERVER, "done_event_race_server") { }
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
1007c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->PostTask(FROM_HERE,
1008c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           base::Bind(&NestedCallback, this));
1009c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&TimeoutCallback),
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromSeconds(9));
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Even though we have a timeout on the Send, it will succeed since for this
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // bug, the reply message comes back and is deserialized, however the done
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // event wasn't set.  So we indirectly use the timeout task to notice if a
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // timeout occurred.
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendAnswerToLife(true, 10000, true);
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!timeout_occurred);
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests http://b/1474092 - that if after the done_event is set but before
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OnObjectSignaled is called another message is sent out, then after its
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// reply comes back OnObjectSignaled will be called for the first message.
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, DoneEventRace) {
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new DoneEventRaceServer());
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new SimpleClient());
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestSyncMessageFilter : public SyncMessageFilter {
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSyncMessageFilter(base::WaitableEvent* shutdown_event,
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        Worker* worker,
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        scoped_refptr<base::MessageLoopProxy> message_loop)
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : SyncMessageFilter(shutdown_event),
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        worker_(worker),
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        message_loop_(message_loop) {
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnFilterAdded(Channel* channel) OVERRIDE {
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncMessageFilter::OnFilterAdded(channel);
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_->PostTask(
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&TestSyncMessageFilter::SendMessageOnHelperThread, this));
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SendMessageOnHelperThread() {
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int answer = 0;
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer));
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(result);
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(answer, 42);
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    worker_->Done();
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TestSyncMessageFilter() {}
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Worker* worker_;
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> message_loop_;
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyncMessageFilterServer : public Worker {
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncMessageFilterServer()
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(Channel::MODE_SERVER, "sync_message_filter_server"),
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        thread_("helper_thread") {
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Thread::Options options;
1074c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    thread_.StartWithOptions(options);
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filter_ = new TestSyncMessageFilter(shutdown_event(), this,
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        thread_.message_loop_proxy());
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel()->AddFilter(filter_.get());
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread thread_;
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<TestSyncMessageFilter> filter_;
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class provides functionality to test the case that a Send on the sync
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// channel does not crash after the channel has been closed.
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ServerSendAfterClose : public Worker {
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ServerSendAfterClose()
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     : Worker(Channel::MODE_SERVER, "simpler_server"),
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       send_result_(true) {
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SendDummy() {
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ListenerThread()->message_loop()->PostTask(
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(base::IgnoreResult(&ServerSendAfterClose::Send),
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              this, new SyncChannelTestMsg_NoArgs));
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool send_result() const {
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return send_result_;
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseChannel();
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool Send(Message* msg) OVERRIDE {
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    send_result_ = Worker::Send(msg);
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return send_result_;
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool send_result_;
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests basic synchronous call
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, SyncMessageFilter) {
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new SyncMessageFilterServer());
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new SimpleClient());
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test the case when the channel is closed and a Send is attempted after that.
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, SendAfterClose) {
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ServerSendAfterClose server;
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server.Start();
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server.done_event()->Wait();
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server.done_event()->Reset();
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server.SendDummy();
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server.done_event()->Wait();
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(server.send_result());
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  server.Shutdown();
11452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RestrictedDispatchServer : public Worker {
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchServer(WaitableEvent* sent_ping_event,
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           WaitableEvent* wait_event)
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("restricted_channel", Channel::MODE_SERVER),
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sent_ping_event_(sent_ping_event),
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        wait_event_(wait_event) { }
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDoPing(int ping) {
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send an asynchronous message that unblocks the caller.
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* msg = new SyncChannelTestMsg_Ping(ping);
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msg->set_unblock(true);
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(msg);
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Signal the event after the message has been sent on the channel, on the
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // IPC thread.
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ipc_thread().message_loop()->PostTask(
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&RestrictedDispatchServer::OnPingSent, this));
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnPingTTL(int ping, int* out) {
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *out = ping;
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wait_event_->Wait();
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread* ListenerThread() { return Worker::ListenerThread(); }
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
11762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchServer, message)
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_PingTTL, OnPingTTL)
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnPingSent() {
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sent_ping_event_->Signal();
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnNoArgs() { }
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* sent_ping_event_;
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* wait_event_;
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NonRestrictedDispatchServer : public Worker {
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NonRestrictedDispatchServer(WaitableEvent* signal_event)
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("non_restricted_channel", Channel::MODE_SERVER),
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        signal_event_(signal_event) {}
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread* ListenerThread() { return Worker::ListenerThread(); }
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDoPingTTL(int ping) {
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int value = 0;
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new SyncChannelTestMsg_PingTTL(ping, &value));
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    signal_event_->Signal();
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
12092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(NonRestrictedDispatchServer, message)
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnNoArgs() { }
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* signal_event_;
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RestrictedDispatchClient : public Worker {
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchClient(WaitableEvent* sent_ping_event,
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           RestrictedDispatchServer* server,
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           NonRestrictedDispatchServer* server2,
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int* success)
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("restricted_channel", Channel::MODE_CLIENT),
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ping_(0),
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_(server),
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server2_(server2),
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        success_(success),
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sent_ping_event_(sent_ping_event) {}
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Incoming messages from our channel should only be dispatched when we
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // send a message on that same channel.
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel()->SetRestrictDispatchChannelGroup(1);
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_->ListenerThread()->message_loop()->PostTask(
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&RestrictedDispatchServer::OnDoPing, server_, 1));
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sent_ping_event_->Wait();
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new SyncChannelTestMsg_NoArgs);
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ping_ == 1)
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++*success_;
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Send failed to dispatch incoming message on same channel";
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    non_restricted_channel_.reset(
12497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        new SyncChannel("non_restricted_channel",
12507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        Channel::MODE_CLIENT,
12517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        this,
12527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        ipc_thread().message_loop_proxy().get(),
12537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        true,
12547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        shutdown_event()));
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_->ListenerThread()->message_loop()->PostTask(
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&RestrictedDispatchServer::OnDoPing, server_, 2));
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sent_ping_event_->Wait();
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check that the incoming message is *not* dispatched when sending on the
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // non restricted channel.
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(piman): there is a possibility of a false positive race condition
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // here, if the message that was posted on the server-side end of the pipe
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // is not visible yet on the client side, but I don't know how to solve this
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // without hooking into the internals of SyncChannel. I haven't seen it in
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // practice (i.e. not setting SetRestrictDispatchToSameChannel does cause
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the following to fail).
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    non_restricted_channel_->Send(new SyncChannelTestMsg_NoArgs);
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ping_ == 1)
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++*success_;
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Send dispatched message from restricted channel";
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new SyncChannelTestMsg_NoArgs);
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ping_ == 2)
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++*success_;
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Send failed to dispatch incoming message on same channel";
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check that the incoming message on the non-restricted channel is
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // dispatched when sending on the restricted channel.
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server2_->ListenerThread()->message_loop()->PostTask(
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&NonRestrictedDispatchServer::OnDoPingTTL, server2_, 3));
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int value = 0;
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new SyncChannelTestMsg_PingTTL(4, &value));
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ping_ == 3 && value == 4)
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++*success_;
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Send failed to dispatch message from unrestricted channel";
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    non_restricted_channel_->Send(new SyncChannelTestMsg_Done);
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    non_restricted_channel_.reset();
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new SyncChannelTestMsg_Done);
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
12982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchClient, message)
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Ping, OnPing)
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_PingTTL, OnPingTTL)
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnPing(int ping) {
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ping_ = ping;
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnPingTTL(int ping, IPC::Message* reply) {
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ping_ = ping;
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This message comes from the NonRestrictedDispatchServer, we have to send
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the reply back manually.
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelTestMsg_PingTTL::WriteReplyParams(reply, ping);
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    non_restricted_channel_->Send(reply);
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ping_;
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchServer* server_;
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NonRestrictedDispatchServer* server2_;
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int* success_;
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* sent_ping_event_;
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SyncChannel> non_restricted_channel_;
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, RestrictedDispatch) {
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent sent_ping_event(false, false);
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent wait_event(false, false);
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchServer* server =
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new RestrictedDispatchServer(&sent_ping_event, &wait_event);
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NonRestrictedDispatchServer* server2 =
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new NonRestrictedDispatchServer(&wait_event);
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int success = 0;
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(server);
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(server2);
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new RestrictedDispatchClient(
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &sent_ping_event, server, server2, &success));
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(4, success);
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test case inspired by crbug.com/108491
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We create two servers that use the same ListenerThread but have
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SetRestrictDispatchToSameChannel set to true.
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We create clients, then use some specific WaitableEvent wait/signalling to
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ensure that messages get dispatched in a way that causes a deadlock due to
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a nested dispatch and an eligible message in a higher-level dispatch's
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// delayed_queue. Specifically, we start with client1 about so send an
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// unblocking message to server1, while the shared listener thread for the
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// servers server1 and server2 is about to send a non-unblocking message to
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// client1. At the same time, client2 will be about to send an unblocking
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// message to server2. Server1 will handle the client1->server1 message by
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// telling server2 to send a non-unblocking message to client2.
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// What should happen is that the send to server2 should find the pending,
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// same-context client2->server2 message to dispatch, causing client2 to
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// unblock then handle the server2->client2 message, so that the shared
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// servers' listener thread can then respond to the client1->server1 message.
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Then client1 can handle the non-unblocking server1->client1 message.
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The old code would end up in a state where the server2->client2 message is
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sent, but the client2->server2 message (which is eligible for dispatch, and
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which is what client2 is waiting for) is stashed in a local delayed_queue
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that has server1's channel context, causing a deadlock.
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WaitableEvents in the events array are used to:
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   event 0: indicate to client1 that server listener is in OnDoServerTask
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   event 1: indicate to client1 that client2 listener is in OnDoClient2Task
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   event 2: indicate to server1 that client2 listener is in OnDoClient2Task
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   event 3: indicate to client2 that server listener is in OnDoServerTask
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RestrictedDispatchDeadlockServer : public Worker {
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockServer(int server_num,
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   WaitableEvent* server_ready_event,
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   WaitableEvent** events,
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   RestrictedDispatchDeadlockServer* peer)
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(server_num == 1 ? "channel1" : "channel2", Channel::MODE_SERVER),
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_num_(server_num),
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_ready_event_(server_ready_event),
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        events_(events),
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        peer_(peer) { }
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDoServerTask() {
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[3]->Signal();
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[2]->Wait();
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[0]->Signal();
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendMessageToClient();
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel()->SetRestrictDispatchChannelGroup(1);
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_ready_event_->Signal();
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread* ListenerThread() { return Worker::ListenerThread(); }
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
14002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockServer, message)
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnNoArgs() {
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (server_num_ == 1) {
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(peer_ != NULL);
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      peer_->SendMessageToClient();
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SendMessageToClient() {
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* msg = new SyncChannelTestMsg_NoArgs;
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msg->set_unblock(false);
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!msg->should_unblock());
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(msg);
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int server_num_;
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* server_ready_event_;
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent** events_;
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockServer* peer_;
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RestrictedDispatchDeadlockClient2 : public Worker {
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockClient2(RestrictedDispatchDeadlockServer* server,
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    WaitableEvent* server_ready_event,
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    WaitableEvent** events)
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("channel2", Channel::MODE_CLIENT),
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_ready_event_(server_ready_event),
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        events_(events),
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        received_msg_(false),
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        received_noarg_reply_(false),
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        done_issued_(false) {}
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_ready_event_->Wait();
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDoClient2Task() {
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[3]->Wait();
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[1]->Signal();
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[2]->Signal();
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(received_msg_ == false);
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* message = new SyncChannelTestMsg_NoArgs;
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message->set_unblock(true);
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(message);
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    received_noarg_reply_ = true;
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread* ListenerThread() { return Worker::ListenerThread(); }
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
14582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockClient2, message)
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnNoArgs() {
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    received_msg_ = true;
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PossiblyDone();
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PossiblyDone() {
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (received_noarg_reply_ && received_msg_) {
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(done_issued_ == false);
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      done_issued_ = true;
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Send(new SyncChannelTestMsg_Done);
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Done();
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* server_ready_event_;
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent** events_;
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool received_msg_;
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool received_noarg_reply_;
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool done_issued_;
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RestrictedDispatchDeadlockClient1 : public Worker {
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockClient1(RestrictedDispatchDeadlockServer* server,
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    RestrictedDispatchDeadlockClient2* peer,
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    WaitableEvent* server_ready_event,
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    WaitableEvent** events)
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("channel1", Channel::MODE_CLIENT),
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_(server),
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        peer_(peer),
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_ready_event_(server_ready_event),
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        events_(events),
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        received_msg_(false),
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        received_noarg_reply_(false),
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        done_issued_(false) {}
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_ready_event_->Wait();
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_->ListenerThread()->message_loop()->PostTask(
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&RestrictedDispatchDeadlockServer::OnDoServerTask, server_));
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    peer_->ListenerThread()->message_loop()->PostTask(
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&RestrictedDispatchDeadlockClient2::OnDoClient2Task, peer_));
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[0]->Wait();
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_[1]->Wait();
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(received_msg_ == false);
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* message = new SyncChannelTestMsg_NoArgs;
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message->set_unblock(true);
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(message);
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    received_noarg_reply_ = true;
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PossiblyDone();
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread* ListenerThread() { return Worker::ListenerThread(); }
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
15222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockClient1, message)
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnNoArgs() {
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    received_msg_ = true;
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PossiblyDone();
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PossiblyDone() {
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (received_noarg_reply_ && received_msg_) {
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(done_issued_ == false);
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      done_issued_ = true;
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Send(new SyncChannelTestMsg_Done);
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Done();
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockServer* server_;
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockClient2* peer_;
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* server_ready_event_;
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent** events_;
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool received_msg_;
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool received_noarg_reply_;
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool done_issued_;
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, RestrictedDispatchDeadlock) {
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A shared worker thread so that server1 and server2 run on one thread.
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread worker_thread("RestrictedDispatchDeadlock");
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(worker_thread.Start());
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent server1_ready(false, false);
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent server2_ready(false, false);
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event0(false, false);
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event1(false, false);
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event2(false, false);
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event3(false, false);
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* events[4] = {&event0, &event1, &event2, &event3};
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockServer* server1;
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockServer* server2;
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockClient1* client1;
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchDeadlockClient2* client2;
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server2 = new RestrictedDispatchDeadlockServer(2, &server2_ready, events,
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 NULL);
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server2->OverrideThread(&worker_thread);
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(server2);
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client2 = new RestrictedDispatchDeadlockClient2(server2, &server2_ready,
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  events);
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(client2);
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server1 = new RestrictedDispatchDeadlockServer(1, &server1_ready, events,
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 server2);
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server1->OverrideThread(&worker_thread);
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(server1);
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client1 = new RestrictedDispatchDeadlockClient1(server1, client2,
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  &server1_ready, events);
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(client1);
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test case inspired by crbug.com/120530
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We create 4 workers that pipe to each other W1->W2->W3->W4->W1 then we send a
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// message that recurses through 3, 4 or 5 steps to make sure, say, W1 can
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// re-enter when called from W4 while it's sending a message to W2.
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The first worker drives the whole test so it must be treated specially.
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RestrictedDispatchPipeWorker : public Worker {
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestrictedDispatchPipeWorker(
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string &channel1,
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WaitableEvent* event1,
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string &channel2,
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WaitableEvent* event2,
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int group,
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int* success)
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(channel1, Channel::MODE_SERVER),
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        event1_(event1),
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        event2_(event2),
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        other_channel_name_(channel2),
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        group_(group),
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        success_(success) {
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnPingTTL(int ping, int* ret) {
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *ret = 0;
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ping)
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    other_channel_->Send(new SyncChannelTestMsg_PingTTL(ping - 1, ret));
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++*ret;
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDone() {
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_first())
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    other_channel_->Send(new SyncChannelTestMsg_Done);
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    other_channel_.reset();
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel()->SetRestrictDispatchChannelGroup(group_);
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_first())
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event1_->Signal();
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event2_->Wait();
16407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    other_channel_.reset(
16417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        new SyncChannel(other_channel_name_,
16427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        Channel::MODE_CLIENT,
16437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        this,
16447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        ipc_thread().message_loop_proxy().get(),
16457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        true,
16467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        shutdown_event()));
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    other_channel_->SetRestrictDispatchChannelGroup(group_);
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!is_first()) {
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event1_->Signal();
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *success_ = 0;
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int value = 0;
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnPingTTL(3, &value);
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *success_ += (value == 3);
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnPingTTL(4, &value);
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *success_ += (value == 4);
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnPingTTL(5, &value);
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *success_ += (value == 5);
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    other_channel_->Send(new SyncChannelTestMsg_Done);
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    other_channel_.reset();
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_first() { return !!success_; }
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
16682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchPipeWorker, message)
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_PingTTL, OnPingTTL)
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, OnDone)
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SyncChannel> other_channel_;
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* event1_;
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* event2_;
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string other_channel_name_;
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int group_;
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int* success_;
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, RestrictedDispatch4WayDeadlock) {
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int success = 0;
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event0(true, false);
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event1(true, false);
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event2(true, false);
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event3(true, false);
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new RestrictedDispatchPipeWorker(
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "channel0", &event0, "channel1", &event1, 1, &success));
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new RestrictedDispatchPipeWorker(
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "channel1", &event1, "channel2", &event2, 2, NULL));
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new RestrictedDispatchPipeWorker(
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "channel2", &event2, "channel3", &event3, 3, NULL));
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new RestrictedDispatchPipeWorker(
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "channel3", &event3, "channel0", &event0, 4, NULL));
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3, success);
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test case inspired by crbug.com/122443
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We want to make sure a reply message with the unblock flag set correctly
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// behaves as a reply, not a regular message.
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We have 3 workers. Server1 will send a message to Server2 (which will block),
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// during which it will dispatch a message comming from Client, at which point
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it will send another message to Server2. While sending that second message it
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will receive a reply from Server1 with the unblock flag.
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ReentrantReplyServer1 : public Worker {
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReentrantReplyServer1(WaitableEvent* server_ready)
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("reentrant_reply1", Channel::MODE_SERVER),
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_ready_(server_ready) { }
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
17207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    server2_channel_.reset(
17217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        new SyncChannel("reentrant_reply2",
17227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        Channel::MODE_CLIENT,
17237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        this,
17247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        ipc_thread().message_loop_proxy().get(),
17257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        true,
17267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        shutdown_event()));
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_ready_->Signal();
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* msg = new SyncChannelTestMsg_Reentrant1();
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server2_channel_->Send(msg);
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server2_channel_.reset();
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
17352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(ReentrantReplyServer1, message)
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Reentrant2, OnReentrant2)
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_REPLY_HANDLER(OnReply)
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnReentrant2() {
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* msg = new SyncChannelTestMsg_Reentrant3();
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server2_channel_->Send(msg);
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnReply(const Message& message) {
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we get here, the Send() will never receive the reply (thus would
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // hang), so abort instead.
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(FATAL) << "Reply message was dispatched";
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* server_ready_;
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SyncChannel> server2_channel_;
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ReentrantReplyServer2 : public Worker {
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReentrantReplyServer2()
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("reentrant_reply2", Channel::MODE_SERVER),
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reply_(NULL) { }
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
17652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const Message& message) OVERRIDE {
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(ReentrantReplyServer2, message)
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER_DELAY_REPLY(
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         SyncChannelTestMsg_Reentrant1, OnReentrant1)
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Reentrant3, OnReentrant3)
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnReentrant1(Message* reply) {
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!reply_);
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reply_ = reply;
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnReentrant3() {
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(reply_);
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* reply = reply_;
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reply_ = NULL;
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reply->set_unblock(true);
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply);
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Message* reply_;
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ReentrantReplyClient : public Worker {
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReentrantReplyClient(WaitableEvent* server_ready)
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker("reentrant_reply1", Channel::MODE_CLIENT),
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_ready_(server_ready) { }
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_ready_->Wait();
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new SyncChannelTestMsg_Reentrant2());
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* server_ready_;
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, ReentrantReply) {
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent server_ready(false, false);
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new ReentrantReplyServer2());
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new ReentrantReplyServer1(&server_ready));
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(new ReentrantReplyClient(&server_ready));
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generate a validated channel ID using Channel::GenerateVerifiedChannelID().
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VerifiedServer : public Worker {
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifiedServer(base::Thread* listener_thread,
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const std::string& channel_name,
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const std::string& reply_text)
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(channel_name, Channel::MODE_SERVER),
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reply_text_(reply_text) {
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Worker::OverrideThread(listener_thread);
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnNestedTestMsg(Message* reply_msg) OVERRIDE {
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << __FUNCTION__ << " Sending reply: " << reply_text_;
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncChannelNestedTestMsg_String::WriteReplyParams(reply_msg, reply_text_);
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(reply_msg);
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(channel()->peer_pid(), base::GetCurrentProcId());
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string reply_text_;
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VerifiedClient : public Worker {
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifiedClient(base::Thread* listener_thread,
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const std::string& channel_name,
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const std::string& expected_text)
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Worker(channel_name, Channel::MODE_CLIENT),
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expected_text_(expected_text) {
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Worker::OverrideThread(listener_thread);
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Run() OVERRIDE {
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string response;
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncMessage* msg = new SyncChannelNestedTestMsg_String(&response);
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool result = Send(msg);
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(result);
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(response, expected_text_);
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // expected_text_ is only used in the above DCHECK. This line suppresses the
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "unused private field" warning in release builds.
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void)expected_text_;
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << __FUNCTION__ << " Received reply: " << response;
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(channel()->peer_pid(), base::GetCurrentProcId());
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string expected_text_;
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Verified() {
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Worker*> workers;
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A shared worker thread for servers
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread server_worker_thread("Verified_ServerListener");
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(server_worker_thread.Start());
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread client_worker_thread("Verified_ClientListener");
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(client_worker_thread.Start());
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string channel_id = Channel::GenerateVerifiedChannelID("Verified");
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Worker* worker;
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new VerifiedServer(&server_worker_thread,
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              channel_id,
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              "Got first message");
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker = new VerifiedClient(&client_worker_thread,
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              channel_id,
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              "Got first message");
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  workers.push_back(worker);
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(workers);
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows needs to send an out-of-band secret to verify the client end of the
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// channel. Test that we still connect correctly in that case.
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IPCSyncChannelTest, Verified) {
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Verified();
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace IPC
1905