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