// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/task_scheduler/post_task.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
#include "mojo/public/cpp/bindings/associated_interface_request.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/lib/multiplex_router.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/bindings/thread_safe_interface_ptr.h"
#include "mojo/public/interfaces/bindings/tests/ping_service.mojom.h"
#include "mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace mojo {
namespace test {
namespace {

using mojo::internal::MultiplexRouter;

class IntegerSenderImpl : public IntegerSender {
 public:
  explicit IntegerSenderImpl(AssociatedInterfaceRequest<IntegerSender> request)
      : binding_(this, std::move(request)) {}

  ~IntegerSenderImpl() override {}

  void set_notify_send_method_called(
      const base::Callback<void(int32_t)>& callback) {
    notify_send_method_called_ = callback;
  }

  void Echo(int32_t value, const EchoCallback& callback) override {
    callback.Run(value);
  }
  void Send(int32_t value) override { notify_send_method_called_.Run(value); }

  AssociatedBinding<IntegerSender>* binding() { return &binding_; }

  void set_connection_error_handler(const base::Closure& handler) {
    binding_.set_connection_error_handler(handler);
  }

 private:
  AssociatedBinding<IntegerSender> binding_;
  base::Callback<void(int32_t)> notify_send_method_called_;
};

class IntegerSenderConnectionImpl : public IntegerSenderConnection {
 public:
  explicit IntegerSenderConnectionImpl(
      InterfaceRequest<IntegerSenderConnection> request)
      : binding_(this, std::move(request)) {}

  ~IntegerSenderConnectionImpl() override {}

  void GetSender(AssociatedInterfaceRequest<IntegerSender> sender) override {
    IntegerSenderImpl* sender_impl = new IntegerSenderImpl(std::move(sender));
    sender_impl->set_connection_error_handler(
        base::Bind(&DeleteSender, sender_impl));
  }

  void AsyncGetSender(const AsyncGetSenderCallback& callback) override {
    IntegerSenderAssociatedPtrInfo ptr_info;
    auto request = MakeRequest(&ptr_info);
    GetSender(std::move(request));
    callback.Run(std::move(ptr_info));
  }

  Binding<IntegerSenderConnection>* binding() { return &binding_; }

 private:
  static void DeleteSender(IntegerSenderImpl* sender) { delete sender; }

  Binding<IntegerSenderConnection> binding_;
};

class AssociatedInterfaceTest : public testing::Test {
 public:
  AssociatedInterfaceTest()
      : main_runner_(base::ThreadTaskRunnerHandle::Get()) {}
  ~AssociatedInterfaceTest() override { base::RunLoop().RunUntilIdle(); }

  void PumpMessages() { base::RunLoop().RunUntilIdle(); }

  template <typename T>
  AssociatedInterfacePtrInfo<T> EmulatePassingAssociatedPtrInfo(
      AssociatedInterfacePtrInfo<T> ptr_info,
      scoped_refptr<MultiplexRouter> source,
      scoped_refptr<MultiplexRouter> target) {
    ScopedInterfaceEndpointHandle handle = ptr_info.PassHandle();
    CHECK(handle.pending_association());
    auto id = source->AssociateInterface(std::move(handle));
    return AssociatedInterfacePtrInfo<T>(target->CreateLocalEndpointHandle(id),
                                         ptr_info.version());
  }

  void CreateRouterPair(scoped_refptr<MultiplexRouter>* router0,
                        scoped_refptr<MultiplexRouter>* router1) {
    MessagePipe pipe;
    *router0 = new MultiplexRouter(std::move(pipe.handle0),
                                   MultiplexRouter::MULTI_INTERFACE, true,
                                   main_runner_);
    *router1 = new MultiplexRouter(std::move(pipe.handle1),
                                   MultiplexRouter::MULTI_INTERFACE, false,
                                   main_runner_);
  }

  void CreateIntegerSenderWithExistingRouters(
      scoped_refptr<MultiplexRouter> router0,
      IntegerSenderAssociatedPtrInfo* ptr_info0,
      scoped_refptr<MultiplexRouter> router1,
      IntegerSenderAssociatedRequest* request1) {
    *request1 = MakeRequest(ptr_info0);
    *ptr_info0 = EmulatePassingAssociatedPtrInfo(std::move(*ptr_info0), router1,
                                                 router0);
  }

  void CreateIntegerSender(IntegerSenderAssociatedPtrInfo* ptr_info,
                           IntegerSenderAssociatedRequest* request) {
    scoped_refptr<MultiplexRouter> router0;
    scoped_refptr<MultiplexRouter> router1;
    CreateRouterPair(&router0, &router1);
    CreateIntegerSenderWithExistingRouters(router1, ptr_info, router0, request);
  }

  // Okay to call from any thread.
  void QuitRunLoop(base::RunLoop* run_loop) {
    if (main_runner_->RunsTasksInCurrentSequence()) {
      run_loop->Quit();
    } else {
      main_runner_->PostTask(
          FROM_HERE,
          base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
                     base::Unretained(this), base::Unretained(run_loop)));
    }
  }

 private:
  base::test::ScopedTaskEnvironment task_environment;
  scoped_refptr<base::SequencedTaskRunner> main_runner_;
};

void DoSetFlagAndRunClosure(bool* flag, const base::Closure& closure) {
  *flag = true;
  closure.Run();
}

void DoExpectValueSetFlagAndRunClosure(int32_t expected_value,
                                       bool* flag,
                                       const base::Closure& closure,
                                       int32_t value) {
  EXPECT_EQ(expected_value, value);
  DoSetFlagAndRunClosure(flag, closure);
}

base::Closure SetFlagAndRunClosure(bool* flag, const base::Closure& closure) {
  return base::Bind(&DoSetFlagAndRunClosure, flag, closure);
}

base::Callback<void(int32_t)> ExpectValueSetFlagAndRunClosure(
    int32_t expected_value,
    bool* flag,
    const base::Closure& closure) {
  return base::Bind(
      &DoExpectValueSetFlagAndRunClosure, expected_value, flag, closure);
}

void Fail() {
  FAIL() << "Unexpected connection error";
}

TEST_F(AssociatedInterfaceTest, InterfacesAtBothEnds) {
  // Bind to the same pipe two associated interfaces, whose implementation lives
  // at different ends. Test that the two don't interfere with each other.

  scoped_refptr<MultiplexRouter> router0;
  scoped_refptr<MultiplexRouter> router1;
  CreateRouterPair(&router0, &router1);

  AssociatedInterfaceRequest<IntegerSender> request;
  IntegerSenderAssociatedPtrInfo ptr_info;
  CreateIntegerSenderWithExistingRouters(router1, &ptr_info, router0, &request);

  IntegerSenderImpl impl0(std::move(request));
  AssociatedInterfacePtr<IntegerSender> ptr0;
  ptr0.Bind(std::move(ptr_info));

  CreateIntegerSenderWithExistingRouters(router0, &ptr_info, router1, &request);

  IntegerSenderImpl impl1(std::move(request));
  AssociatedInterfacePtr<IntegerSender> ptr1;
  ptr1.Bind(std::move(ptr_info));

  base::RunLoop run_loop, run_loop2;
  bool ptr0_callback_run = false;
  ptr0->Echo(123, ExpectValueSetFlagAndRunClosure(123, &ptr0_callback_run,
                                                  run_loop.QuitClosure()));

  bool ptr1_callback_run = false;
  ptr1->Echo(456, ExpectValueSetFlagAndRunClosure(456, &ptr1_callback_run,
                                                  run_loop2.QuitClosure()));

  run_loop.Run();
  run_loop2.Run();
  EXPECT_TRUE(ptr0_callback_run);
  EXPECT_TRUE(ptr1_callback_run);

  bool ptr0_error_callback_run = false;
  base::RunLoop run_loop3;
  ptr0.set_connection_error_handler(
      SetFlagAndRunClosure(&ptr0_error_callback_run, run_loop3.QuitClosure()));

  impl0.binding()->Close();
  run_loop3.Run();
  EXPECT_TRUE(ptr0_error_callback_run);

  bool impl1_error_callback_run = false;
  base::RunLoop run_loop4;
  impl1.binding()->set_connection_error_handler(
      SetFlagAndRunClosure(&impl1_error_callback_run, run_loop4.QuitClosure()));

  ptr1.reset();
  run_loop4.Run();
  EXPECT_TRUE(impl1_error_callback_run);
}

class TestSender {
 public:
  TestSender()
      : task_runner_(base::CreateSequencedTaskRunnerWithTraits({})),
        next_sender_(nullptr),
        max_value_to_send_(-1) {}

  // The following three methods are called on the corresponding sender thread.
  void SetUp(IntegerSenderAssociatedPtrInfo ptr_info,
             TestSender* next_sender,
             int32_t max_value_to_send) {
    CHECK(task_runner()->RunsTasksInCurrentSequence());

    ptr_.Bind(std::move(ptr_info));
    next_sender_ = next_sender ? next_sender : this;
    max_value_to_send_ = max_value_to_send;
  }

  void Send(int32_t value) {
    CHECK(task_runner()->RunsTasksInCurrentSequence());

    if (value > max_value_to_send_)
      return;

    ptr_->Send(value);

    next_sender_->task_runner()->PostTask(
        FROM_HERE,
        base::Bind(&TestSender::Send, base::Unretained(next_sender_), ++value));
  }

  void TearDown() {
    CHECK(task_runner()->RunsTasksInCurrentSequence());

    ptr_.reset();
  }

  base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }

 private:
  scoped_refptr<base::SequencedTaskRunner> task_runner_;
  TestSender* next_sender_;
  int32_t max_value_to_send_;

  AssociatedInterfacePtr<IntegerSender> ptr_;
};

class TestReceiver {
 public:
  TestReceiver()
      : task_runner_(base::CreateSequencedTaskRunnerWithTraits({})),
        expected_calls_(0) {}

  void SetUp(AssociatedInterfaceRequest<IntegerSender> request0,
             AssociatedInterfaceRequest<IntegerSender> request1,
             size_t expected_calls,
             const base::Closure& notify_finish) {
    CHECK(task_runner()->RunsTasksInCurrentSequence());

    impl0_.reset(new IntegerSenderImpl(std::move(request0)));
    impl0_->set_notify_send_method_called(
        base::Bind(&TestReceiver::SendMethodCalled, base::Unretained(this)));
    impl1_.reset(new IntegerSenderImpl(std::move(request1)));
    impl1_->set_notify_send_method_called(
        base::Bind(&TestReceiver::SendMethodCalled, base::Unretained(this)));

    expected_calls_ = expected_calls;
    notify_finish_ = notify_finish;
  }

  void TearDown() {
    CHECK(task_runner()->RunsTasksInCurrentSequence());

    impl0_.reset();
    impl1_.reset();
  }

  base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }
  const std::vector<int32_t>& values() const { return values_; }

 private:
  void SendMethodCalled(int32_t value) {
    values_.push_back(value);

    if (values_.size() >= expected_calls_)
      notify_finish_.Run();
  }

  scoped_refptr<base::SequencedTaskRunner> task_runner_;
  size_t expected_calls_;

  std::unique_ptr<IntegerSenderImpl> impl0_;
  std::unique_ptr<IntegerSenderImpl> impl1_;

  std::vector<int32_t> values_;

  base::Closure notify_finish_;
};

class NotificationCounter {
 public:
  NotificationCounter(size_t total_count, const base::Closure& notify_finish)
      : total_count_(total_count),
        current_count_(0),
        notify_finish_(notify_finish) {}

  ~NotificationCounter() {}

  // Okay to call from any thread.
  void OnGotNotification() {
    bool finshed = false;
    {
      base::AutoLock locker(lock_);
      CHECK_LT(current_count_, total_count_);
      current_count_++;
      finshed = current_count_ == total_count_;
    }

    if (finshed)
      notify_finish_.Run();
  }

 private:
  base::Lock lock_;
  const size_t total_count_;
  size_t current_count_;
  base::Closure notify_finish_;
};

TEST_F(AssociatedInterfaceTest, MultiThreadAccess) {
  // Set up four associated interfaces on a message pipe. Use the inteface
  // pointers on four threads in parallel; run the interface implementations on
  // two threads. Test that multi-threaded access works.

  const int32_t kMaxValue = 1000;
  MessagePipe pipe;
  scoped_refptr<MultiplexRouter> router0;
  scoped_refptr<MultiplexRouter> router1;
  CreateRouterPair(&router0, &router1);

  AssociatedInterfaceRequest<IntegerSender> requests[4];
  IntegerSenderAssociatedPtrInfo ptr_infos[4];
  for (size_t i = 0; i < 4; ++i) {
    CreateIntegerSenderWithExistingRouters(router1, &ptr_infos[i], router0,
                                           &requests[i]);
  }

  TestSender senders[4];
  for (size_t i = 0; i < 4; ++i) {
    senders[i].task_runner()->PostTask(
        FROM_HERE, base::Bind(&TestSender::SetUp, base::Unretained(&senders[i]),
                              base::Passed(&ptr_infos[i]), nullptr,
                              kMaxValue * (i + 1) / 4));
  }

  base::RunLoop run_loop;
  TestReceiver receivers[2];
  NotificationCounter counter(
      2, base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
                    base::Unretained(this), base::Unretained(&run_loop)));
  for (size_t i = 0; i < 2; ++i) {
    receivers[i].task_runner()->PostTask(
        FROM_HERE,
        base::Bind(&TestReceiver::SetUp, base::Unretained(&receivers[i]),
                   base::Passed(&requests[2 * i]),
                   base::Passed(&requests[2 * i + 1]),
                   static_cast<size_t>(kMaxValue / 2),
                   base::Bind(&NotificationCounter::OnGotNotification,
                              base::Unretained(&counter))));
  }

  for (size_t i = 0; i < 4; ++i) {
    senders[i].task_runner()->PostTask(
        FROM_HERE, base::Bind(&TestSender::Send, base::Unretained(&senders[i]),
                              kMaxValue * i / 4 + 1));
  }

  run_loop.Run();

  for (size_t i = 0; i < 4; ++i) {
    base::RunLoop run_loop;
    senders[i].task_runner()->PostTaskAndReply(
        FROM_HERE,
        base::Bind(&TestSender::TearDown, base::Unretained(&senders[i])),
        base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
                   base::Unretained(this), base::Unretained(&run_loop)));
    run_loop.Run();
  }

  for (size_t i = 0; i < 2; ++i) {
    base::RunLoop run_loop;
    receivers[i].task_runner()->PostTaskAndReply(
        FROM_HERE,
        base::Bind(&TestReceiver::TearDown, base::Unretained(&receivers[i])),
        base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
                   base::Unretained(this), base::Unretained(&run_loop)));
    run_loop.Run();
  }

  EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[0].values().size());
  EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[1].values().size());

  std::vector<int32_t> all_values;
  all_values.insert(all_values.end(), receivers[0].values().begin(),
                    receivers[0].values().end());
  all_values.insert(all_values.end(), receivers[1].values().begin(),
                    receivers[1].values().end());

  std::sort(all_values.begin(), all_values.end());
  for (size_t i = 0; i < all_values.size(); ++i)
    ASSERT_EQ(static_cast<int32_t>(i + 1), all_values[i]);
}

TEST_F(AssociatedInterfaceTest, FIFO) {
  // Set up four associated interfaces on a message pipe. Use the inteface
  // pointers on four threads; run the interface implementations on two threads.
  // Take turns to make calls using the four pointers. Test that FIFO-ness is
  // preserved.

  const int32_t kMaxValue = 100;
  MessagePipe pipe;
  scoped_refptr<MultiplexRouter> router0;
  scoped_refptr<MultiplexRouter> router1;
  CreateRouterPair(&router0, &router1);

  AssociatedInterfaceRequest<IntegerSender> requests[4];
  IntegerSenderAssociatedPtrInfo ptr_infos[4];
  for (size_t i = 0; i < 4; ++i) {
    CreateIntegerSenderWithExistingRouters(router1, &ptr_infos[i], router0,
                                           &requests[i]);
  }

  TestSender senders[4];
  for (size_t i = 0; i < 4; ++i) {
    senders[i].task_runner()->PostTask(
        FROM_HERE,
        base::Bind(&TestSender::SetUp, base::Unretained(&senders[i]),
                   base::Passed(&ptr_infos[i]),
                   base::Unretained(&senders[(i + 1) % 4]), kMaxValue));
  }

  base::RunLoop run_loop;
  TestReceiver receivers[2];
  NotificationCounter counter(
      2, base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
                    base::Unretained(this), base::Unretained(&run_loop)));
  for (size_t i = 0; i < 2; ++i) {
    receivers[i].task_runner()->PostTask(
        FROM_HERE,
        base::Bind(&TestReceiver::SetUp, base::Unretained(&receivers[i]),
                   base::Passed(&requests[2 * i]),
                   base::Passed(&requests[2 * i + 1]),
                   static_cast<size_t>(kMaxValue / 2),
                   base::Bind(&NotificationCounter::OnGotNotification,
                              base::Unretained(&counter))));
  }

  senders[0].task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&TestSender::Send, base::Unretained(&senders[0]), 1));

  run_loop.Run();

  for (size_t i = 0; i < 4; ++i) {
    base::RunLoop run_loop;
    senders[i].task_runner()->PostTaskAndReply(
        FROM_HERE,
        base::Bind(&TestSender::TearDown, base::Unretained(&senders[i])),
        base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
                   base::Unretained(this), base::Unretained(&run_loop)));
    run_loop.Run();
  }

  for (size_t i = 0; i < 2; ++i) {
    base::RunLoop run_loop;
    receivers[i].task_runner()->PostTaskAndReply(
        FROM_HERE,
        base::Bind(&TestReceiver::TearDown, base::Unretained(&receivers[i])),
        base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
                   base::Unretained(this), base::Unretained(&run_loop)));
    run_loop.Run();
  }

  EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[0].values().size());
  EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[1].values().size());

  for (size_t i = 0; i < 2; ++i) {
    for (size_t j = 1; j < receivers[i].values().size(); ++j)
      EXPECT_LT(receivers[i].values()[j - 1], receivers[i].values()[j]);
  }
}

void CaptureInt32(int32_t* storage,
                  const base::Closure& closure,
                  int32_t value) {
  *storage = value;
  closure.Run();
}

void CaptureSenderPtrInfo(IntegerSenderAssociatedPtr* storage,
                          const base::Closure& closure,
                          IntegerSenderAssociatedPtrInfo info) {
  storage->Bind(std::move(info));
  closure.Run();
}

TEST_F(AssociatedInterfaceTest, PassAssociatedInterfaces) {
  IntegerSenderConnectionPtr connection_ptr;
  IntegerSenderConnectionImpl connection(MakeRequest(&connection_ptr));

  IntegerSenderAssociatedPtr sender0;
  connection_ptr->GetSender(MakeRequest(&sender0));

  int32_t echoed_value = 0;
  base::RunLoop run_loop;
  sender0->Echo(123, base::Bind(&CaptureInt32, &echoed_value,
                                run_loop.QuitClosure()));
  run_loop.Run();
  EXPECT_EQ(123, echoed_value);

  IntegerSenderAssociatedPtr sender1;
  base::RunLoop run_loop2;
  connection_ptr->AsyncGetSender(
      base::Bind(&CaptureSenderPtrInfo, &sender1, run_loop2.QuitClosure()));
  run_loop2.Run();
  EXPECT_TRUE(sender1);

  base::RunLoop run_loop3;
  sender1->Echo(456, base::Bind(&CaptureInt32, &echoed_value,
                                run_loop3.QuitClosure()));
  run_loop3.Run();
  EXPECT_EQ(456, echoed_value);
}

TEST_F(AssociatedInterfaceTest, BindingWaitAndPauseWhenNoAssociatedInterfaces) {
  IntegerSenderConnectionPtr connection_ptr;
  IntegerSenderConnectionImpl connection(MakeRequest(&connection_ptr));

  IntegerSenderAssociatedPtr sender0;
  connection_ptr->GetSender(MakeRequest(&sender0));

  EXPECT_FALSE(connection.binding()->HasAssociatedInterfaces());
  // There are no associated interfaces running on the pipe yet. It is okay to
  // pause.
  connection.binding()->PauseIncomingMethodCallProcessing();
  connection.binding()->ResumeIncomingMethodCallProcessing();

  // There are no associated interfaces running on the pipe yet. It is okay to
  // wait.
  EXPECT_TRUE(connection.binding()->WaitForIncomingMethodCall());

  // The previous wait has dispatched the GetSender request message, therefore
  // an associated interface has been set up on the pipe. It is not allowed to
  // wait or pause.
  EXPECT_TRUE(connection.binding()->HasAssociatedInterfaces());
}

class PingServiceImpl : public PingService {
 public:
  explicit PingServiceImpl(PingServiceAssociatedRequest request)
      : binding_(this, std::move(request)) {}
  ~PingServiceImpl() override {}

  AssociatedBinding<PingService>& binding() { return binding_; }

  void set_ping_handler(const base::Closure& handler) {
    ping_handler_ = handler;
  }

  // PingService:
  void Ping(const PingCallback& callback) override {
    if (!ping_handler_.is_null())
      ping_handler_.Run();
    callback.Run();
  }

 private:
  AssociatedBinding<PingService> binding_;
  base::Closure ping_handler_;
};

class PingProviderImpl : public AssociatedPingProvider {
 public:
  explicit PingProviderImpl(AssociatedPingProviderRequest request)
      : binding_(this, std::move(request)) {}
  ~PingProviderImpl() override {}

  // AssociatedPingProvider:
  void GetPing(PingServiceAssociatedRequest request) override {
    ping_services_.emplace_back(new PingServiceImpl(std::move(request)));

    if (expected_bindings_count_ > 0 &&
        ping_services_.size() == expected_bindings_count_ &&
        !quit_waiting_.is_null()) {
      expected_bindings_count_ = 0;
      base::ResetAndReturn(&quit_waiting_).Run();
    }
  }

  std::vector<std::unique_ptr<PingServiceImpl>>& ping_services() {
    return ping_services_;
  }

  void WaitForBindings(size_t count) {
    DCHECK(quit_waiting_.is_null());

    expected_bindings_count_ = count;
    base::RunLoop loop;
    quit_waiting_ = loop.QuitClosure();
    loop.Run();
  }

 private:
  Binding<AssociatedPingProvider> binding_;
  std::vector<std::unique_ptr<PingServiceImpl>> ping_services_;
  size_t expected_bindings_count_ = 0;
  base::Closure quit_waiting_;
};

class CallbackFilter : public MessageReceiver {
 public:
  explicit CallbackFilter(const base::Closure& callback)
      : callback_(callback) {}
  ~CallbackFilter() override {}

  static std::unique_ptr<CallbackFilter> Wrap(const base::Closure& callback) {
    return std::make_unique<CallbackFilter>(callback);
  }

  // MessageReceiver:
  bool Accept(Message* message) override {
    callback_.Run();
    return true;
  }

 private:
  const base::Closure callback_;
};

// Verifies that filters work as expected on associated bindings, i.e. that
// they're notified in order, before dispatch; and that each associated
// binding in a group operates with its own set of filters.
TEST_F(AssociatedInterfaceTest, BindingWithFilters) {
  AssociatedPingProviderPtr provider;
  PingProviderImpl provider_impl(MakeRequest(&provider));

  PingServiceAssociatedPtr ping_a, ping_b;
  provider->GetPing(MakeRequest(&ping_a));
  provider->GetPing(MakeRequest(&ping_b));
  provider_impl.WaitForBindings(2);

  ASSERT_EQ(2u, provider_impl.ping_services().size());
  PingServiceImpl& ping_a_impl = *provider_impl.ping_services()[0];
  PingServiceImpl& ping_b_impl = *provider_impl.ping_services()[1];

  int a_status, b_status;
  auto handler_helper = [] (int* a_status, int* b_status, int expected_a_status,
                            int new_a_status, int expected_b_status,
                            int new_b_status) {
    EXPECT_EQ(expected_a_status, *a_status);
    EXPECT_EQ(expected_b_status, *b_status);
    *a_status = new_a_status;
    *b_status = new_b_status;
  };
  auto create_handler = [&] (int expected_a_status, int new_a_status,
                             int expected_b_status, int new_b_status) {
    return base::Bind(handler_helper, &a_status, &b_status, expected_a_status,
                      new_a_status, expected_b_status, new_b_status);
  };

  ping_a_impl.binding().AddFilter(
      CallbackFilter::Wrap(create_handler(0, 1, 0, 0)));
  ping_a_impl.binding().AddFilter(
      CallbackFilter::Wrap(create_handler(1, 2, 0, 0)));
  ping_a_impl.set_ping_handler(create_handler(2, 3, 0, 0));

  ping_b_impl.binding().AddFilter(
      CallbackFilter::Wrap(create_handler(3, 3, 0, 1)));
  ping_b_impl.binding().AddFilter(
      CallbackFilter::Wrap(create_handler(3, 3, 1, 2)));
  ping_b_impl.set_ping_handler(create_handler(3, 3, 2, 3));

  for (int i = 0; i < 10; ++i) {
    a_status = 0;
    b_status = 0;

    {
      base::RunLoop loop;
      ping_a->Ping(loop.QuitClosure());
      loop.Run();
    }

    EXPECT_EQ(3, a_status);
    EXPECT_EQ(0, b_status);

    {
      base::RunLoop loop;
      ping_b->Ping(loop.QuitClosure());
      loop.Run();
    }

    EXPECT_EQ(3, a_status);
    EXPECT_EQ(3, b_status);
  }
}

TEST_F(AssociatedInterfaceTest, AssociatedPtrFlushForTesting) {
  AssociatedInterfaceRequest<IntegerSender> request;
  IntegerSenderAssociatedPtrInfo ptr_info;
  CreateIntegerSender(&ptr_info, &request);

  IntegerSenderImpl impl0(std::move(request));
  AssociatedInterfacePtr<IntegerSender> ptr0;
  ptr0.Bind(std::move(ptr_info));
  ptr0.set_connection_error_handler(base::Bind(&Fail));

  bool ptr0_callback_run = false;
  ptr0->Echo(123, ExpectValueSetFlagAndRunClosure(123, &ptr0_callback_run,
                                                  base::DoNothing()));
  ptr0.FlushForTesting();
  EXPECT_TRUE(ptr0_callback_run);
}

void SetBool(bool* value) {
  *value = true;
}

template <typename T>
void SetBoolWithUnusedParameter(bool* value, T unused) {
  *value = true;
}

TEST_F(AssociatedInterfaceTest, AssociatedPtrFlushForTestingWithClosedPeer) {
  AssociatedInterfaceRequest<IntegerSender> request;
  IntegerSenderAssociatedPtrInfo ptr_info;
  CreateIntegerSender(&ptr_info, &request);

  AssociatedInterfacePtr<IntegerSender> ptr0;
  ptr0.Bind(std::move(ptr_info));
  bool called = false;
  ptr0.set_connection_error_handler(base::Bind(&SetBool, &called));
  request = nullptr;

  ptr0.FlushForTesting();
  EXPECT_TRUE(called);
  ptr0.FlushForTesting();
}

TEST_F(AssociatedInterfaceTest, AssociatedBindingFlushForTesting) {
  AssociatedInterfaceRequest<IntegerSender> request;
  IntegerSenderAssociatedPtrInfo ptr_info;
  CreateIntegerSender(&ptr_info, &request);

  IntegerSenderImpl impl0(std::move(request));
  impl0.set_connection_error_handler(base::Bind(&Fail));
  AssociatedInterfacePtr<IntegerSender> ptr0;
  ptr0.Bind(std::move(ptr_info));

  bool ptr0_callback_run = false;
  ptr0->Echo(123, ExpectValueSetFlagAndRunClosure(123, &ptr0_callback_run,
                                                  base::DoNothing()));
  // Because the flush is sent from the binding, it only guarantees that the
  // request has been received, not the response. The second flush waits for the
  // response to be received.
  impl0.binding()->FlushForTesting();
  impl0.binding()->FlushForTesting();
  EXPECT_TRUE(ptr0_callback_run);
}

TEST_F(AssociatedInterfaceTest,
       AssociatedBindingFlushForTestingWithClosedPeer) {
  scoped_refptr<MultiplexRouter> router0;
  scoped_refptr<MultiplexRouter> router1;
  CreateRouterPair(&router0, &router1);

  AssociatedInterfaceRequest<IntegerSender> request;
  {
    IntegerSenderAssociatedPtrInfo ptr_info;
    CreateIntegerSenderWithExistingRouters(router1, &ptr_info, router0,
                                           &request);
  }

  IntegerSenderImpl impl(std::move(request));
  bool called = false;
  impl.set_connection_error_handler(base::Bind(&SetBool, &called));
  impl.binding()->FlushForTesting();
  EXPECT_TRUE(called);
  impl.binding()->FlushForTesting();
}

TEST_F(AssociatedInterfaceTest, BindingFlushForTesting) {
  IntegerSenderConnectionPtr ptr;
  IntegerSenderConnectionImpl impl(MakeRequest(&ptr));
  bool called = false;
  ptr->AsyncGetSender(base::Bind(
      &SetBoolWithUnusedParameter<IntegerSenderAssociatedPtrInfo>, &called));
  EXPECT_FALSE(called);
  impl.binding()->set_connection_error_handler(base::Bind(&Fail));
  // Because the flush is sent from the binding, it only guarantees that the
  // request has been received, not the response. The second flush waits for the
  // response to be received.
  impl.binding()->FlushForTesting();
  impl.binding()->FlushForTesting();
  EXPECT_TRUE(called);
}

TEST_F(AssociatedInterfaceTest, BindingFlushForTestingWithClosedPeer) {
  IntegerSenderConnectionPtr ptr;
  IntegerSenderConnectionImpl impl(MakeRequest(&ptr));
  bool called = false;
  impl.binding()->set_connection_error_handler(base::Bind(&SetBool, &called));
  ptr.reset();
  EXPECT_FALSE(called);
  impl.binding()->FlushForTesting();
  EXPECT_TRUE(called);
  impl.binding()->FlushForTesting();
}

TEST_F(AssociatedInterfaceTest, StrongBindingFlushForTesting) {
  IntegerSenderConnectionPtr ptr;
  auto binding =
      MakeStrongBinding(std::make_unique<IntegerSenderConnectionImpl>(
                            IntegerSenderConnectionRequest{}),
                        MakeRequest(&ptr));
  bool called = false;
  IntegerSenderAssociatedPtr sender_ptr;
  ptr->GetSender(MakeRequest(&sender_ptr));
  sender_ptr->Echo(1, base::Bind(&SetBoolWithUnusedParameter<int>, &called));
  EXPECT_FALSE(called);
  // Because the flush is sent from the binding, it only guarantees that the
  // request has been received, not the response. The second flush waits for the
  // response to be received.
  ASSERT_TRUE(binding);
  binding->FlushForTesting();
  ASSERT_TRUE(binding);
  binding->FlushForTesting();
  EXPECT_TRUE(called);
}

TEST_F(AssociatedInterfaceTest, StrongBindingFlushForTestingWithClosedPeer) {
  IntegerSenderConnectionPtr ptr;
  bool called = false;
  auto binding =
      MakeStrongBinding(std::make_unique<IntegerSenderConnectionImpl>(
                            IntegerSenderConnectionRequest{}),
                        MakeRequest(&ptr));
  binding->set_connection_error_handler(base::Bind(&SetBool, &called));
  ptr.reset();
  EXPECT_FALSE(called);
  ASSERT_TRUE(binding);
  binding->FlushForTesting();
  EXPECT_TRUE(called);
  ASSERT_FALSE(binding);
}

TEST_F(AssociatedInterfaceTest, PtrFlushForTesting) {
  IntegerSenderConnectionPtr ptr;
  IntegerSenderConnectionImpl impl(MakeRequest(&ptr));
  bool called = false;
  ptr.set_connection_error_handler(base::Bind(&Fail));
  ptr->AsyncGetSender(base::Bind(
      &SetBoolWithUnusedParameter<IntegerSenderAssociatedPtrInfo>, &called));
  EXPECT_FALSE(called);
  ptr.FlushForTesting();
  EXPECT_TRUE(called);
}

TEST_F(AssociatedInterfaceTest, PtrFlushForTestingWithClosedPeer) {
  IntegerSenderConnectionPtr ptr;
  MakeRequest(&ptr);
  bool called = false;
  ptr.set_connection_error_handler(base::Bind(&SetBool, &called));
  EXPECT_FALSE(called);
  ptr.FlushForTesting();
  EXPECT_TRUE(called);
  ptr.FlushForTesting();
}

TEST_F(AssociatedInterfaceTest, AssociatedBindingConnectionErrorWithReason) {
  AssociatedInterfaceRequest<IntegerSender> request;
  IntegerSenderAssociatedPtrInfo ptr_info;
  CreateIntegerSender(&ptr_info, &request);

  IntegerSenderImpl impl(std::move(request));
  AssociatedInterfacePtr<IntegerSender> ptr;
  ptr.Bind(std::move(ptr_info));

  base::RunLoop run_loop;
  impl.binding()->set_connection_error_with_reason_handler(base::Bind(
      [](const base::Closure& quit_closure, uint32_t custom_reason,
         const std::string& description) {
        EXPECT_EQ(123u, custom_reason);
        EXPECT_EQ("farewell", description);
        quit_closure.Run();
      },
      run_loop.QuitClosure()));

  ptr.ResetWithReason(123u, "farewell");

  run_loop.Run();
}

TEST_F(AssociatedInterfaceTest,
       PendingAssociatedBindingConnectionErrorWithReason) {
  // Test that AssociatedBinding is notified with connection error when the
  // interface hasn't associated with a message pipe and the peer is closed.

  IntegerSenderAssociatedPtr ptr;
  IntegerSenderImpl impl(MakeRequest(&ptr));

  base::RunLoop run_loop;
  impl.binding()->set_connection_error_with_reason_handler(base::Bind(
      [](const base::Closure& quit_closure, uint32_t custom_reason,
         const std::string& description) {
        EXPECT_EQ(123u, custom_reason);
        EXPECT_EQ("farewell", description);
        quit_closure.Run();
      },
      run_loop.QuitClosure()));

  ptr.ResetWithReason(123u, "farewell");

  run_loop.Run();
}

TEST_F(AssociatedInterfaceTest, AssociatedPtrConnectionErrorWithReason) {
  AssociatedInterfaceRequest<IntegerSender> request;
  IntegerSenderAssociatedPtrInfo ptr_info;
  CreateIntegerSender(&ptr_info, &request);

  IntegerSenderImpl impl(std::move(request));
  AssociatedInterfacePtr<IntegerSender> ptr;
  ptr.Bind(std::move(ptr_info));

  base::RunLoop run_loop;
  ptr.set_connection_error_with_reason_handler(base::Bind(
      [](const base::Closure& quit_closure, uint32_t custom_reason,
         const std::string& description) {
        EXPECT_EQ(456u, custom_reason);
        EXPECT_EQ("farewell", description);
        quit_closure.Run();
      },
      run_loop.QuitClosure()));

  impl.binding()->CloseWithReason(456u, "farewell");

  run_loop.Run();
}

TEST_F(AssociatedInterfaceTest, PendingAssociatedPtrConnectionErrorWithReason) {
  // Test that AssociatedInterfacePtr is notified with connection error when the
  // interface hasn't associated with a message pipe and the peer is closed.

  IntegerSenderAssociatedPtr ptr;
  auto request = MakeRequest(&ptr);

  base::RunLoop run_loop;
  ptr.set_connection_error_with_reason_handler(base::Bind(
      [](const base::Closure& quit_closure, uint32_t custom_reason,
         const std::string& description) {
        EXPECT_EQ(456u, custom_reason);
        EXPECT_EQ("farewell", description);
        quit_closure.Run();
      },
      run_loop.QuitClosure()));

  request.ResetWithReason(456u, "farewell");

  run_loop.Run();
}

TEST_F(AssociatedInterfaceTest, AssociatedRequestResetWithReason) {
  AssociatedInterfaceRequest<IntegerSender> request;
  IntegerSenderAssociatedPtrInfo ptr_info;
  CreateIntegerSender(&ptr_info, &request);

  AssociatedInterfacePtr<IntegerSender> ptr;
  ptr.Bind(std::move(ptr_info));

  base::RunLoop run_loop;
  ptr.set_connection_error_with_reason_handler(base::Bind(
      [](const base::Closure& quit_closure, uint32_t custom_reason,
         const std::string& description) {
        EXPECT_EQ(789u, custom_reason);
        EXPECT_EQ("long time no see", description);
        quit_closure.Run();
      },
      run_loop.QuitClosure()));

  request.ResetWithReason(789u, "long time no see");

  run_loop.Run();
}

TEST_F(AssociatedInterfaceTest, ThreadSafeAssociatedInterfacePtr) {
  IntegerSenderConnectionPtr connection_ptr;
  IntegerSenderConnectionImpl connection(MakeRequest(&connection_ptr));

  IntegerSenderAssociatedPtr sender;
  connection_ptr->GetSender(MakeRequest(&sender));

  scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr> thread_safe_sender =
      ThreadSafeIntegerSenderAssociatedPtr::Create(std::move(sender));

  {
    // Test the thread safe pointer can be used from the interface ptr thread.
    int32_t echoed_value = 0;
    base::RunLoop run_loop;
    (*thread_safe_sender)
        ->Echo(123, base::Bind(&CaptureInt32, &echoed_value,
                               run_loop.QuitClosure()));
    run_loop.Run();
    EXPECT_EQ(123, echoed_value);
  }

  // Test the thread safe pointer can be used from another thread.
  base::RunLoop run_loop;

  auto run_method = base::Bind(
      [](const scoped_refptr<base::TaskRunner>& main_task_runner,
         const base::Closure& quit_closure,
         const scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr>&
             thread_safe_sender) {
        auto done_callback = base::Bind(
            [](const scoped_refptr<base::TaskRunner>& main_task_runner,
               const base::Closure& quit_closure,
               scoped_refptr<base::SequencedTaskRunner> sender_sequence_runner,
               int32_t result) {
              EXPECT_EQ(123, result);
              // Validate the callback is invoked on the calling sequence.
              EXPECT_TRUE(sender_sequence_runner->RunsTasksInCurrentSequence());
              // Notify the run_loop to quit.
              main_task_runner->PostTask(FROM_HERE, quit_closure);
            });
        scoped_refptr<base::SequencedTaskRunner> current_sequence_runner =
            base::SequencedTaskRunnerHandle::Get();
        (*thread_safe_sender)
            ->Echo(123, base::Bind(done_callback, main_task_runner,
                                   quit_closure, current_sequence_runner));
      },
      base::SequencedTaskRunnerHandle::Get(), run_loop.QuitClosure(),
      thread_safe_sender);
  base::CreateSequencedTaskRunnerWithTraits({})->PostTask(FROM_HERE,
                                                          run_method);

  // Block until the method callback is called on the background thread.
  run_loop.Run();
}

struct ForwarderTestContext {
  IntegerSenderConnectionPtr connection_ptr;
  std::unique_ptr<IntegerSenderConnectionImpl> interface_impl;
  IntegerSenderAssociatedRequest sender_request;
};

TEST_F(AssociatedInterfaceTest,
       ThreadSafeAssociatedInterfacePtrWithTaskRunner) {
  const scoped_refptr<base::SequencedTaskRunner> other_thread_task_runner =
      base::CreateSequencedTaskRunnerWithTraits({});

  ForwarderTestContext* context = new ForwarderTestContext();
  IntegerSenderAssociatedPtrInfo sender_info;
  base::WaitableEvent sender_info_bound_event(
      base::WaitableEvent::ResetPolicy::MANUAL,
      base::WaitableEvent::InitialState::NOT_SIGNALED);
  auto setup = [](base::WaitableEvent* sender_info_bound_event,
                  IntegerSenderAssociatedPtrInfo* sender_info,
                  ForwarderTestContext* context) {
    context->interface_impl = std::make_unique<IntegerSenderConnectionImpl>(
        MakeRequest(&context->connection_ptr));

    auto sender_request = MakeRequest(sender_info);
    context->connection_ptr->GetSender(std::move(sender_request));

    // Unblock the main thread as soon as |sender_info| is set.
    sender_info_bound_event->Signal();
  };
  other_thread_task_runner->PostTask(
      FROM_HERE,
      base::Bind(setup, &sender_info_bound_event, &sender_info, context));
  sender_info_bound_event.Wait();

  // Create a ThreadSafeAssociatedPtr that binds on the background thread and is
  // associated with |connection_ptr| there.
  scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr> thread_safe_ptr =
      ThreadSafeIntegerSenderAssociatedPtr::Create(std::move(sender_info),
                                                   other_thread_task_runner);

  // Issue a call on the thread-safe ptr immediately. Note that this may happen
  // before the interface is bound on the background thread, and that must be
  // OK.
  {
    auto echo_callback =
        base::Bind([](const base::Closure& quit_closure, int32_t result) {
          EXPECT_EQ(123, result);
          quit_closure.Run();
        });
    base::RunLoop run_loop;
    (*thread_safe_ptr)
        ->Echo(123, base::Bind(echo_callback, run_loop.QuitClosure()));

    // Block until the method callback is called.
    run_loop.Run();
  }

  other_thread_task_runner->DeleteSoon(FROM_HERE, context);

  // Reset the pointer now so the InterfacePtr associated resources can be
  // deleted before the background thread's message loop is invalidated.
  thread_safe_ptr = nullptr;
}

class DiscardingAssociatedPingProviderProvider
    : public AssociatedPingProviderProvider {
 public:
  void GetPingProvider(
      AssociatedPingProviderAssociatedRequest request) override {}
};

TEST_F(AssociatedInterfaceTest, CloseWithoutBindingAssociatedRequest) {
  DiscardingAssociatedPingProviderProvider ping_provider_provider;
  mojo::Binding<AssociatedPingProviderProvider> binding(
      &ping_provider_provider);
  AssociatedPingProviderProviderPtr provider_provider;
  binding.Bind(mojo::MakeRequest(&provider_provider));
  AssociatedPingProviderAssociatedPtr provider;
  provider_provider->GetPingProvider(mojo::MakeRequest(&provider));
  PingServiceAssociatedPtr ping;
  provider->GetPing(mojo::MakeRequest(&ping));
  base::RunLoop run_loop;
  ping.set_connection_error_handler(run_loop.QuitClosure());
  run_loop.Run();
}

TEST_F(AssociatedInterfaceTest, AssociateWithDisconnectedPipe) {
  IntegerSenderAssociatedPtr sender;
  AssociateWithDisconnectedPipe(MakeRequest(&sender).PassHandle());
  sender->Send(42);
}

TEST_F(AssociatedInterfaceTest, AsyncErrorHandlersWhenClosingMasterInterface) {
  // Ensures that associated interface error handlers are not invoked
  // synchronously when the master interface pipe is closed. Regression test for
  // https://crbug.com/864731.

  IntegerSenderConnectionPtr connection_ptr;
  IntegerSenderConnectionImpl connection(MakeRequest(&connection_ptr));

  base::RunLoop loop;
  bool error_handler_invoked = false;
  IntegerSenderAssociatedPtr sender0;
  connection_ptr->GetSender(MakeRequest(&sender0));
  sender0.set_connection_error_handler(base::BindLambdaForTesting([&] {
    error_handler_invoked = true;
    loop.Quit();
  }));

  // This should not trigger the error handler synchronously...
  connection_ptr.reset();
  EXPECT_FALSE(error_handler_invoked);

  // ...but it should be triggered once we spin the scheduler.
  loop.Run();
  EXPECT_TRUE(error_handler_invoked);
}

}  // namespace
}  // namespace test
}  // namespace mojo
