// Copyright 2014 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 "shell/shell_test_base.h"

#include "base/bind.h"
#include "base/i18n/time_formatting.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "mojo/public/cpp/bindings/error_handler.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "mojo/public/cpp/system/core.h"
#include "services/test_service/test_request_tracker.mojom.h"
#include "services/test_service/test_service.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

using mojo::Callback;
using mojo::test::ServiceReport;
using mojo::test::ServiceReportPtr;
using mojo::test::TestService;
using mojo::test::TestTimeService;
using mojo::test::TestServicePtr;
using mojo::test::TestTimeServicePtr;
using mojo::test::TestTrackedRequestService;
using mojo::test::TestTrackedRequestServicePtr;

namespace shell {
namespace test {
namespace {

void GetReportCallback(base::MessageLoop* loop,
                       std::vector<ServiceReport>* reports_out,
                       mojo::Array<ServiceReportPtr> report) {
  for (size_t i = 0; i < report.size(); i++)
    reports_out->push_back(*report[i]);
  loop->QuitWhenIdle();
}

class ShellTestBaseTest : public ShellTestBase {
 public:
  // Convenience helpers for use as callbacks in tests.
  template <typename T>
  base::Callback<void()> SetAndQuit(T* val, T result) {
    return base::Bind(&ShellTestBaseTest::SetAndQuitImpl<T>,
                      base::Unretained(this), val, result);
  }
  template <typename T>
  base::Callback<void(T result)> SetAndQuit(T* val) {
    return base::Bind(&ShellTestBaseTest::SetAndQuitImpl<T>,
                      base::Unretained(this), val);
  }
  static GURL test_app_url() { return GURL("mojo:test_app"); }

  void GetReport(std::vector<ServiceReport>* report) {
    ConnectToService(GURL("mojo:test_request_tracker_app"), &request_tracking_);
    request_tracking_->GetReport(base::Bind(&GetReportCallback,
                                            base::Unretained(message_loop()),
                                            base::Unretained(report)));
    message_loop()->Run();
  }

 private:
  template <typename T>
  void SetAndQuitImpl(T* val, T result) {
    *val = result;
    message_loop()->QuitWhenIdle();
  }
  TestTrackedRequestServicePtr request_tracking_;
};

class QuitMessageLoopErrorHandler : public mojo::ErrorHandler {
 public:
  QuitMessageLoopErrorHandler() {}
  ~QuitMessageLoopErrorHandler() override {}

  // |mojo::ErrorHandler| implementation:
  void OnConnectionError() override {
    base::MessageLoop::current()->QuitWhenIdle();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(QuitMessageLoopErrorHandler);
};

// Tests that we can connect to a single service within a single app.
TEST_F(ShellTestBaseTest, ConnectBasic) {
  TestServicePtr service;
  ConnectToService(test_app_url(), &service);

  bool was_run = false;
  service->Ping(SetAndQuit<bool>(&was_run, true));
  message_loop()->Run();
  EXPECT_TRUE(was_run);
  EXPECT_FALSE(service.encountered_error());

  service.reset();

  // This will run until the test app has actually quit (which it will,
  // since we killed the only connection to it).
  message_loop()->Run();
}

// Tests that trying to connect to a service fails properly if the service
// doesn't exist. Implicit in this test is verification that the shell
// terminates if no services are running.
TEST_F(ShellTestBaseTest, ConnectInvalidService) {
  TestServicePtr test_service;
  ConnectToService(GURL("mojo:non_existent_service"), &test_service);

  bool was_run = false;
  test_service->Ping(SetAndQuit<bool>(&was_run, true));

  // This will quit because there's nothing running.
  message_loop()->Run();
  EXPECT_FALSE(was_run);

  // It may have quit before an error was processed.
  if (!test_service.encountered_error()) {
    QuitMessageLoopErrorHandler quitter;
    test_service.set_error_handler(&quitter);
    message_loop()->Run();
    EXPECT_TRUE(test_service.encountered_error());
  }

  test_service.reset();
}

// Tests that we can connect to a single service within a single app using
// a network based loader instead of local files.
// TODO(tim): Disabled because network service leaks NSS at exit, meaning
// subsequent tests can't init properly.
TEST_F(ShellTestBaseTest, DISABLED_ConnectBasicNetwork) {
  TestServicePtr service;
  ConnectToService(test_app_url(), &service);

  bool was_run = false;
  service->Ping(SetAndQuit<bool>(&was_run, true));
  message_loop()->Run();
  EXPECT_TRUE(was_run);
  EXPECT_FALSE(service.encountered_error());

  // Note that use of the network service is implicit in this test.
  // Since TestService is not the only service in use, the shell won't auto
  // magically exit when TestService is destroyed (unlike ConnectBasic).
  // Tearing down the shell context will kill connections. The shell loop will
  // exit as soon as no more apps are connected.
  // TODO(tim): crbug.com/392685.  Calling this explicitly shouldn't be
  // necessary once the shell terminates if the primordial app exits, which
  // we could enforce here by resetting |service|.
  shell_context()->application_manager()->TerminateShellConnections();
  message_loop()->Run();  // Waits for all connections to die.
}

// Tests that trying to connect to a service over network fails preoprly
// if the service doesn't exist.
// TODO(tim): Disabled because network service leaks NSS at exit, meaning
// subsequent tests can't init properly.
TEST_F(ShellTestBaseTest, DISABLED_ConnectInvalidServiceNetwork) {
  TestServicePtr test_service;
  ConnectToService(GURL("http://example.com/non_existent_service"),
                   &test_service);
  QuitMessageLoopErrorHandler quitter;
  test_service.set_error_handler(&quitter);
  bool was_run = false;
  test_service->Ping(SetAndQuit<bool>(&was_run, true));
  message_loop()->Run();
  EXPECT_TRUE(test_service.encountered_error());

  // TODO(tim): crbug.com/392685.  Calling this explicitly shouldn't be
  // necessary once the shell terminates if the primordial app exits, which
  // we could enforce here by resetting |service|.
  shell_context()->application_manager()->TerminateShellConnections();
  message_loop()->Run();  // Waits for all connections to die.
}

// Similar to ConnectBasic, but causes the app to instantiate multiple
// service implementation objects and verifies the shell can reach both.
TEST_F(ShellTestBaseTest, ConnectMultipleInstancesPerApp) {
  {
    TestServicePtr service1, service2;
    ConnectToService(test_app_url(), &service1);
    ConnectToService(test_app_url(), &service2);

    bool was_run1 = false;
    bool was_run2 = false;
    service1->Ping(SetAndQuit<bool>(&was_run1, true));
    message_loop()->Run();
    service2->Ping(SetAndQuit<bool>(&was_run2, true));
    message_loop()->Run();
    EXPECT_TRUE(was_run1);
    EXPECT_TRUE(was_run2);
    EXPECT_FALSE(service1.encountered_error());
    EXPECT_FALSE(service2.encountered_error());
  }
  message_loop()->Run();
}

// Tests that service A and service B, both in App 1, can talk to each other
// and parameters are passed around properly.
TEST_F(ShellTestBaseTest, ConnectDifferentServicesInSingleApp) {
  // Have a TestService GetPartyTime on a TestTimeService in the same app.
  int64 time_message;
  TestServicePtr service;
  ConnectToService(test_app_url(), &service);
  service->ConnectToAppAndGetTime(test_app_url().spec(),
                                  SetAndQuit<int64>(&time_message));
  message_loop()->Run();

  // Verify by hitting the TimeService directly.
  TestTimeServicePtr time_service;
  ConnectToService(test_app_url(), &time_service);
  int64 party_time;
  time_service->GetPartyTime(SetAndQuit<int64>(&party_time));
  message_loop()->Run();

  EXPECT_EQ(time_message, party_time);
}

// Tests that a service A in App 1 can talk to service B in App 2 and
// parameters are passed around properly.
TEST_F(ShellTestBaseTest, ConnectDifferentServicesInDifferentApps) {
  int64 time_message;
  TestServicePtr service;
  ConnectToService(test_app_url(), &service);
  service->ConnectToAppAndGetTime("mojo:test_request_tracker_app",
                                  SetAndQuit<int64>(&time_message));
  message_loop()->Run();

  // Verify by hitting the TimeService in the request tracker app directly.
  TestTimeServicePtr time_service;
  ConnectToService(GURL("mojo:test_request_tracker_app"), &time_service);
  int64 party_time;
  time_service->GetPartyTime(SetAndQuit<int64>(&party_time));
  message_loop()->Run();

  EXPECT_EQ(time_message, party_time);
}

// Tests that service A in App 1 can be a client of service B in App 2.
TEST_F(ShellTestBaseTest, ConnectServiceAsClientOfSeparateApp) {
  TestServicePtr service;
  ConnectToService(test_app_url(), &service);
  service->StartTrackingRequests(message_loop()->QuitWhenIdleClosure());
  service->Ping(Callback<void()>());
  message_loop()->Run();

  for (int i = 0; i < 8; i++)
    service->Ping(Callback<void()>());
  service->Ping(message_loop()->QuitWhenIdleClosure());
  message_loop()->Run();

  // If everything worked properly, the tracking service should report
  // 10 pings to TestService.
  std::vector<ServiceReport> reports;
  GetReport(&reports);
  ASSERT_EQ(1U, reports.size());
  EXPECT_EQ(TestService::Name_, reports[0].service_name);
  EXPECT_EQ(10U, reports[0].total_requests);
}

// Connect several services together and use the tracking service to verify
// communication.
TEST_F(ShellTestBaseTest, ConnectManyClientsAndServices) {
  TestServicePtr service;
  TestTimeServicePtr time_service;

  // Make a request to the TestService and have it contact TimeService in the
  // tracking app. Do all this with tracking enabled, meaning both services
  // are connected as clients of the TrackedRequestService.
  ConnectToService(test_app_url(), &service);
  service->StartTrackingRequests(message_loop()->QuitWhenIdleClosure());
  message_loop()->Run();
  for (int i = 0; i < 5; i++)
    service->Ping(Callback<void()>());
  int64 time_result;
  service->ConnectToAppAndGetTime("mojo:test_request_tracker_app",
                                  SetAndQuit<int64>(&time_result));
  message_loop()->Run();

  // Also make a few requests to the TimeService in the test_app.
  ConnectToService(test_app_url(), &time_service);
  time_service->StartTrackingRequests(message_loop()->QuitWhenIdleClosure());
  time_service->GetPartyTime(Callback<void(uint64_t)>());
  message_loop()->Run();
  for (int i = 0; i < 18; i++)
    time_service->GetPartyTime(Callback<void(uint64_t)>());
  // Flush the tasks with one more to quit.
  int64 party_time = 0;
  time_service->GetPartyTime(SetAndQuit<int64>(&party_time));
  message_loop()->Run();

  std::vector<ServiceReport> reports;
  GetReport(&reports);
  ASSERT_EQ(3U, reports.size());
  EXPECT_EQ(TestService::Name_, reports[0].service_name);
  EXPECT_EQ(6U, reports[0].total_requests);
  EXPECT_EQ(TestTimeService::Name_, reports[1].service_name);
  EXPECT_EQ(1U, reports[1].total_requests);
  EXPECT_EQ(TestTimeService::Name_, reports[2].service_name);
  EXPECT_EQ(20U, reports[2].total_requests);
}

}  // namespace
}  // namespace test
}  // namespace shell
