// 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 "base/at_exit.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "mojo/data_pipe_utils/data_pipe_utils.h"
#include "mojo/message_pump/message_pump_mojo.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/services/network/interfaces/network_service.mojom.h"
#include "shell/crash/crash_upload.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace breakpad {
namespace {

class MockURLLoader : public mojo::URLLoader {
 public:
  MockURLLoader() : called_(false) {}
  ~MockURLLoader() override {}

  bool called() const { return called_; }

  std::string GetLastContent() {
    std::string result;
    mojo::common::BlockingCopyToString(body_.Pass(), &result);
    return result;
  }

 private:
  // Overriden from mojo::NetworkService.
  void Start(mojo::URLRequestPtr request,
             const StartCallback& callback) override {
    called_ = true;
    mojo::URLResponsePtr response = mojo::URLResponse::New();
    response->status_code = 200;
    body_ = request->body[0].Pass();
    callback.Run(response.Pass());
  }
  void FollowRedirect(const FollowRedirectCallback& callback) override {}
  void QueryStatus(const QueryStatusCallback& callback) override {}

  bool called_;
  mojo::ScopedDataPipeConsumerHandle body_;
};

class MockNetworkService : public mojo::NetworkService {
 public:
  MockNetworkService() : binding_(&mock_url_loader_) {}
  ~MockNetworkService() override {}

  MockURLLoader* url_loader() { return &mock_url_loader_; }

 private:
  // Overriden from mojo::NetworkService.
  void CreateURLLoader(
      mojo::InterfaceRequest<mojo::URLLoader> loader) override {
    binding_.Bind(loader.Pass());
  }
  void GetCookieStore(
      mojo::InterfaceRequest<mojo::CookieStore> cookie_store) override {}
  void CreateWebSocket(
      mojo::InterfaceRequest<mojo::WebSocket> socket) override {}
  void CreateTCPBoundSocket(
      mojo::NetAddressPtr local_address,
      mojo::InterfaceRequest<mojo::TCPBoundSocket> bound_socket,
      const CreateTCPBoundSocketCallback& callback) override {}
  void CreateTCPConnectedSocket(
      mojo::NetAddressPtr remote_address,
      mojo::ScopedDataPipeConsumerHandle send_stream,
      mojo::ScopedDataPipeProducerHandle receive_stream,
      mojo::InterfaceRequest<mojo::TCPConnectedSocket> client_socket,
      const CreateTCPConnectedSocketCallback& callback) override {}
  void CreateUDPSocket(
      mojo::InterfaceRequest<mojo::UDPSocket> socket) override {}
  void CreateHttpServer(mojo::NetAddressPtr local_address,
                        mojo::HttpServerDelegatePtr delegate,
                        const CreateHttpServerCallback& callback) override {}
  void RegisterURLLoaderInterceptor(
      mojo::URLLoaderInterceptorFactoryPtr factory) override {}
  void CreateHostResolver(
      mojo::InterfaceRequest<mojo::HostResolver> host_resolver) override {}

  MockURLLoader mock_url_loader_;
  mojo::Binding<mojo::URLLoader> binding_;
};

std::string GetDumpContent(const base::FilePath& path) {
  return "--" + path.BaseName().value() + "\r\n";
}

void CreateValidDump(const base::FilePath& path, const base::Time& time) {
  std::string content = GetDumpContent(path);
  base::WriteFile(path, content.data(), content.size());
  base::TouchFile(path, time, time);
}

int CountFiles(const base::FilePath& path) {
  base::FileEnumerator files(path, false, base::FileEnumerator::FILES);
  int result = 0;
  for (base::FilePath file = files.Next(); !file.empty(); file = files.Next())
    ++result;
  return result;
}

base::FilePath GetSentinelPath(const base::FilePath& path) {
  return path.Append("upload.sentinel");
}

class CrashUploadTest : public testing::Test {
 public:
  CrashUploadTest()
      : loop_(mojo::common::MessagePumpMojo::Create()),
        binding_(&mock_network_service_, GetProxy(&network_service_)) {}

  void SetUp() override { ASSERT_TRUE(dumps_dir_.CreateUniqueTempDir()); }

  void RebindNetworkService() {
    binding_.Close();
    binding_.Bind(GetProxy(&network_service_));
  }

 protected:
  base::ShadowingAtExitManager at_exit_;
  base::MessageLoop loop_;
  MockNetworkService mock_network_service_;
  mojo::NetworkServicePtr network_service_;
  mojo::Binding<mojo::NetworkService> binding_;
  base::ScopedTempDir dumps_dir_;
};

// Tests that reports can be uploaded and that only the most recent report is
// uploaded.
TEST_F(CrashUploadTest, UploadToServer) {
  for (int i = 0; i < 3; ++i) {
    CreateValidDump(dumps_dir_.path().Append(base::StringPrintf("%d.dmp", i)),
                    base::Time::Now() - base::TimeDelta::FromHours(i));
  }

  UploadCrashes(dumps_dir_.path(), loop_.task_runner().get(),
                network_service_.Pass());
  loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
  base::RunLoop().Run();

  EXPECT_TRUE(mock_network_service_.url_loader()->called());
  EXPECT_TRUE(base::PathExists(GetSentinelPath(dumps_dir_.path())));
  EXPECT_EQ(GetDumpContent(dumps_dir_.path().Append("0.dmp")),
            mock_network_service_.url_loader()->GetLastContent());
  EXPECT_EQ(1, CountFiles(dumps_dir_.path()));
}

// Tests that nothing happen when there is nothing to upload.
TEST_F(CrashUploadTest, NothingToUpload) {
  UploadCrashes(dumps_dir_.path(), loop_.task_runner().get(),
                network_service_.Pass());
  loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
  base::RunLoop().Run();

  EXPECT_FALSE(mock_network_service_.url_loader()->called());
  EXPECT_EQ(0, CountFiles(dumps_dir_.path()));
}

// Tests that spurious reports are deleted but none are uploaded when there is a
// recent sentinel file. Check that the report is uploaded when the sentinel is
// old enough.
TEST_F(CrashUploadTest, UploadGuardedBySentinel) {
  for (int i = 0; i < 3; ++i) {
    CreateValidDump(dumps_dir_.path().Append(base::StringPrintf("%d.dmp", i)),
                    base::Time::Now() - base::TimeDelta::FromHours(i));
  }
  base::FilePath sentinel = GetSentinelPath(dumps_dir_.path());
  base::WriteFile(sentinel, nullptr, 0);
  base::TouchFile(sentinel,
                  base::Time::Now() - base::TimeDelta::FromMinutes(30),
                  base::Time::Now() - base::TimeDelta::FromMinutes(30));

  UploadCrashes(dumps_dir_.path(), loop_.task_runner().get(),
                network_service_.Pass());
  loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
  base::RunLoop().Run();

  EXPECT_FALSE(mock_network_service_.url_loader()->called());
  EXPECT_TRUE(base::PathExists(GetSentinelPath(dumps_dir_.path())));
  EXPECT_EQ(2, CountFiles(dumps_dir_.path()));

  // Send the sentinel in the past.
  base::TouchFile(sentinel,
                  base::Time::Now() - base::TimeDelta::FromMinutes(90),
                  base::Time::Now() - base::TimeDelta::FromMinutes(90));

  RebindNetworkService();
  UploadCrashes(dumps_dir_.path(), loop_.task_runner().get(),
                network_service_.Pass());
  loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
  base::RunLoop().Run();

  EXPECT_TRUE(mock_network_service_.url_loader()->called());
  EXPECT_TRUE(base::PathExists(GetSentinelPath(dumps_dir_.path())));
  EXPECT_EQ(GetDumpContent(dumps_dir_.path().Append("0.dmp")),
            mock_network_service_.url_loader()->GetLastContent());
  EXPECT_EQ(1, CountFiles(dumps_dir_.path()));
}

}  // namespace
}  // namespace breakpad
