// Copyright 2019 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 "remoting/signaling/remoting_log_to_server.h"

#include "base/test/mock_callback.h"
#include "base/test/scoped_task_environment.h"
#include "remoting/base/fake_oauth_token_getter.h"
#include "remoting/proto/remoting/v1/telemetry_service.grpc.pb.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace remoting {

namespace {

using testing::_;

}  // namespace

class RemotingLogToServerTest : public testing::Test {
 public:
  RemotingLogToServerTest() {
    EXPECT_EQ(ServerLogEntry::ME2ME, log_to_server_.mode());
    log_to_server_.create_log_entry_ = mock_create_log_entry_.Get();
  }

  ~RemotingLogToServerTest() override {
    task_environment_.FastForwardUntilNoTasksRemain();
  }

 protected:
  const net::BackoffEntry& GetBackoffEntry() const {
    return log_to_server_.backoff_;
  }

  int GetMaxSendLogAttempts() const {
    return log_to_server_.kMaxSendLogAttempts;
  }

  using CreateLogEntryResponseCallback =
      RemotingLogToServer::CreateLogEntryResponseCallback;

  base::test::TaskEnvironment task_environment_{
      base::test::TaskEnvironment::TimeSource::MOCK_TIME};

  base::MockCallback<RemotingLogToServer::CreateLogEntryCallback>
      mock_create_log_entry_;

  RemotingLogToServer log_to_server_{
      ServerLogEntry::ME2ME,
      std::make_unique<FakeOAuthTokenGetter>(OAuthTokenGetter::SUCCESS,
                                             "fake_email",
                                             "fake_access_token")};
};

TEST_F(RemotingLogToServerTest, SuccessfullySendOneLog) {
  EXPECT_CALL(mock_create_log_entry_, Run(_, _))
      .WillOnce([&](const apis::v1::CreateLogEntryRequest& request,
                    CreateLogEntryResponseCallback callback) {
        ASSERT_EQ(1, request.payload().entry().field_size());
        ASSERT_EQ("test-key", request.payload().entry().field(0).key());
        ASSERT_EQ("test-value", request.payload().entry().field(0).value());
        std::move(callback).Run(grpc::Status::OK, {});
      });

  ServerLogEntry entry;
  entry.Set("test-key", "test-value");
  log_to_server_.Log(entry);

  task_environment_.FastForwardUntilNoTasksRemain();

  ASSERT_EQ(0, GetBackoffEntry().failure_count());
}

TEST_F(RemotingLogToServerTest, FailedToSend_RetryWithBackoff) {
  EXPECT_CALL(mock_create_log_entry_, Run(_, _))
      .Times(GetMaxSendLogAttempts())
      .WillRepeatedly([&](const apis::v1::CreateLogEntryRequest& request,
                          CreateLogEntryResponseCallback callback) {
        ASSERT_EQ(1, request.payload().entry().field_size());
        ASSERT_EQ("test-key", request.payload().entry().field(0).key());
        ASSERT_EQ("test-value", request.payload().entry().field(0).value());
        std::move(callback).Run(
            grpc::Status(grpc::StatusCode::UNAVAILABLE, "unavailable"), {});
      });

  ServerLogEntry entry;
  entry.Set("test-key", "test-value");
  log_to_server_.Log(entry);

  for (int i = 1; i <= GetMaxSendLogAttempts(); i++) {
    task_environment_.FastForwardBy(GetBackoffEntry().GetTimeUntilRelease());
    ASSERT_EQ(i, GetBackoffEntry().failure_count());
  }
}

TEST_F(RemotingLogToServerTest, FailedToSendTwoLogs_RetryThenSucceeds) {
  CreateLogEntryResponseCallback response_callback_1;
  CreateLogEntryResponseCallback response_callback_2;
  EXPECT_CALL(mock_create_log_entry_, Run(_, _))
      .WillOnce([&](const apis::v1::CreateLogEntryRequest& request,
                    CreateLogEntryResponseCallback callback) {
        ASSERT_EQ(1, request.payload().entry().field_size());
        ASSERT_EQ("test-key-1", request.payload().entry().field(0).key());
        ASSERT_EQ("test-value-1", request.payload().entry().field(0).value());
        response_callback_1 = std::move(callback);
      })
      .WillOnce([&](const apis::v1::CreateLogEntryRequest& request,
                    CreateLogEntryResponseCallback callback) {
        ASSERT_EQ(1, request.payload().entry().field_size());
        ASSERT_EQ("test-key-2", request.payload().entry().field(0).key());
        ASSERT_EQ("test-value-2", request.payload().entry().field(0).value());
        response_callback_2 = std::move(callback);
      })
      .WillOnce([&](const apis::v1::CreateLogEntryRequest& request,
                    CreateLogEntryResponseCallback callback) {
        ASSERT_EQ(1, request.payload().entry().field_size());
        ASSERT_EQ("test-key-1", request.payload().entry().field(0).key());
        ASSERT_EQ("test-value-1", request.payload().entry().field(0).value());
        response_callback_1 = std::move(callback);
      })
      .WillOnce([&](const apis::v1::CreateLogEntryRequest& request,
                    CreateLogEntryResponseCallback callback) {
        ASSERT_EQ(1, request.payload().entry().field_size());
        ASSERT_EQ("test-key-2", request.payload().entry().field(0).key());
        ASSERT_EQ("test-value-2", request.payload().entry().field(0).value());
        response_callback_2 = std::move(callback);
      });

  ServerLogEntry entry_1;
  entry_1.Set("test-key-1", "test-value-1");
  log_to_server_.Log(entry_1);
  task_environment_.FastForwardUntilNoTasksRemain();

  ServerLogEntry entry_2;
  entry_2.Set("test-key-2", "test-value-2");
  log_to_server_.Log(entry_2);
  task_environment_.FastForwardUntilNoTasksRemain();

  ASSERT_EQ(0, GetBackoffEntry().failure_count());

  std::move(response_callback_1)
      .Run(grpc::Status(grpc::StatusCode::UNAVAILABLE, "unavailable"), {});
  task_environment_.FastForwardUntilNoTasksRemain();
  std::move(response_callback_2)
      .Run(grpc::Status(grpc::StatusCode::UNAVAILABLE, "unavailable"), {});
  task_environment_.FastForwardUntilNoTasksRemain();
  ASSERT_EQ(2, GetBackoffEntry().failure_count());

  std::move(response_callback_1).Run(grpc::Status::OK, {});
  std::move(response_callback_2).Run(grpc::Status::OK, {});
  task_environment_.FastForwardUntilNoTasksRemain();
  ASSERT_EQ(0, GetBackoffEntry().failure_count());
}

}  // namespace remoting
