// 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 "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/test_support/test_support.h"
#include "mojo/public/cpp/utility/run_loop.h"
#include "mojo/public/interfaces/bindings/tests/ping_service.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace mojo {
namespace {

const double kMojoTicksPerSecond = 1000000.0;

double MojoTicksToSeconds(MojoTimeTicks ticks) {
  return ticks / kMojoTicksPerSecond;
}

class PingServiceImpl : public test::PingService {
 public:
  explicit PingServiceImpl() {}
  ~PingServiceImpl() override {}

  // |PingService| methods:
  void Ping(const Callback<void()>& callback) override;

 private:
  MOJO_DISALLOW_COPY_AND_ASSIGN(PingServiceImpl);
};

void PingServiceImpl::Ping(const Callback<void()>& callback) {
  callback.Run();
}

class PingPongTest {
 public:
  explicit PingPongTest(test::PingServicePtr service);

  void Run(unsigned int iterations);

 private:
  void OnPingDone();

  test::PingServicePtr service_;
  unsigned int iterations_to_run_;
  unsigned int current_iterations_;

  MOJO_DISALLOW_COPY_AND_ASSIGN(PingPongTest);
};

PingPongTest::PingPongTest(test::PingServicePtr service)
    : service_(service.Pass()) {
}

void PingPongTest::Run(unsigned int iterations) {
  iterations_to_run_ = iterations;
  current_iterations_ = 0;

  service_->Ping([this]() { OnPingDone(); });
  RunLoop::current()->Run();
}

void PingPongTest::OnPingDone() {
  current_iterations_++;
  if (current_iterations_ >= iterations_to_run_) {
    RunLoop::current()->Quit();
    return;
  }

  service_->Ping([this]() { OnPingDone(); });
}

struct BoundPingService {
  BoundPingService() : binding(&impl) {
    binding.Bind(GetProxy(&service));
  }

  PingServiceImpl impl;
  test::PingServicePtr service;
  Binding<test::PingService> binding;
};

class MojoBindingsPerftest : public testing::Test {
 protected:
  Environment env_;
  RunLoop run_loop_;
};

TEST_F(MojoBindingsPerftest, InProcessPingPong) {
  test::PingServicePtr service;
  PingServiceImpl impl;
  Binding<test::PingService> binding(&impl, GetProxy(&service));
  PingPongTest test(service.Pass());

  {
    const unsigned int kIterations = 100000;
    const MojoTimeTicks start_time = MojoGetTimeTicksNow();
    test.Run(kIterations);
    const MojoTimeTicks end_time = MojoGetTimeTicksNow();
    test::LogPerfResult(
        "InProcessPingPong", "0_Inactive",
        kIterations / MojoTicksToSeconds(end_time - start_time),
        "pings/second");
  }

  {
    const size_t kNumInactiveServices = 1000;
    BoundPingService* inactive_services =
        new BoundPingService[kNumInactiveServices];

    const unsigned int kIterations = 10000;
    const MojoTimeTicks start_time = MojoGetTimeTicksNow();
    test.Run(kIterations);
    const MojoTimeTicks end_time = MojoGetTimeTicksNow();
    test::LogPerfResult(
        "InProcessPingPong", "1000_Inactive",
        kIterations / MojoTicksToSeconds(end_time - start_time),
        "pings/second");

    delete[] inactive_services;
  }
}

}  // namespace
}  // namespace mojo
