//
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "update_engine/libcurl_http_fetcher.h"

#include <string>

#include <brillo/message_loops/fake_message_loop.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "update_engine/common/fake_hardware.h"
#include "update_engine/common/mock_proxy_resolver.h"
#include "update_engine/mock_libcurl_http_fetcher.h"

using std::string;

namespace chromeos_update_engine {

namespace {
constexpr char kHeaderName[] = "X-Goog-Test-Header";
}

class LibcurlHttpFetcherTest : public ::testing::Test {
 protected:
  void SetUp() override {
    loop_.SetAsCurrent();
    fake_hardware_.SetIsOfficialBuild(true);
    fake_hardware_.SetIsOOBEEnabled(false);
  }

  brillo::FakeMessageLoop loop_{nullptr};
  FakeHardware fake_hardware_;
  MockLibcurlHttpFetcher libcurl_fetcher_{nullptr, &fake_hardware_};
  UnresolvedHostStateMachine state_machine_;
};

TEST_F(LibcurlHttpFetcherTest, GetEmptyHeaderValueTest) {
  const string header_value = "";
  string actual_header_value;
  libcurl_fetcher_.SetHeader(kHeaderName, header_value);
  EXPECT_TRUE(libcurl_fetcher_.GetHeader(kHeaderName, &actual_header_value));
  EXPECT_EQ("", actual_header_value);
}

TEST_F(LibcurlHttpFetcherTest, GetHeaderTest) {
  const string header_value = "This-is-value 123";
  string actual_header_value;
  libcurl_fetcher_.SetHeader(kHeaderName, header_value);
  EXPECT_TRUE(libcurl_fetcher_.GetHeader(kHeaderName, &actual_header_value));
  EXPECT_EQ(header_value, actual_header_value);
}

TEST_F(LibcurlHttpFetcherTest, GetNonExistentHeaderValueTest) {
  string actual_header_value;
  // Skip |SetHeaader()| call.
  EXPECT_FALSE(libcurl_fetcher_.GetHeader(kHeaderName, &actual_header_value));
  // Even after a failed |GetHeaderValue()|, enforce that the passed pointer to
  // modifiable string was cleared to be empty.
  EXPECT_EQ("", actual_header_value);
}

TEST_F(LibcurlHttpFetcherTest, GetHeaderEdgeCaseTest) {
  const string header_value = "\a\b\t\v\f\r\\ edge:-case: \a\b\t\v\f\r\\";
  string actual_header_value;
  libcurl_fetcher_.SetHeader(kHeaderName, header_value);
  EXPECT_TRUE(libcurl_fetcher_.GetHeader(kHeaderName, &actual_header_value));
  EXPECT_EQ(header_value, actual_header_value);
}

TEST_F(LibcurlHttpFetcherTest, InvalidURLTest) {
  int no_network_max_retries = 1;
  libcurl_fetcher_.set_no_network_max_retries(no_network_max_retries);

  libcurl_fetcher_.BeginTransfer("not-a-URL");
  while (loop_.PendingTasks()) {
    loop_.RunOnce(true);
  }

  EXPECT_EQ(libcurl_fetcher_.get_no_network_max_retries(),
            no_network_max_retries);
}

TEST_F(LibcurlHttpFetcherTest, CouldNotResolveHostTest) {
  int no_network_max_retries = 1;
  libcurl_fetcher_.set_no_network_max_retries(no_network_max_retries);

  libcurl_fetcher_.BeginTransfer("https://An-uNres0lvable-uRl.invalid");

  // It's slower on Android that libcurl handle may not finish within 1 cycle.
  // Will need to wait for more cycles until it finishes. Original test didn't
  // correctly handle when we need to re-watch libcurl fds.
  while (loop_.PendingTasks() &&
         libcurl_fetcher_.GetAuxiliaryErrorCode() == ErrorCode::kSuccess) {
    loop_.RunOnce(true);
  }

  EXPECT_EQ(libcurl_fetcher_.GetAuxiliaryErrorCode(),
            ErrorCode::kUnresolvedHostError);

  while (loop_.PendingTasks()) {
    loop_.RunOnce(true);
  }
  // The auxilary error code should've have been changed.
  EXPECT_EQ(libcurl_fetcher_.GetAuxiliaryErrorCode(),
            ErrorCode::kUnresolvedHostError);

  // If libcurl fails to resolve the name, we call res_init() to reload
  // resolv.conf and retry exactly once more. See crbug.com/982813 for details.
  EXPECT_EQ(libcurl_fetcher_.get_no_network_max_retries(),
            no_network_max_retries + 1);
}

TEST_F(LibcurlHttpFetcherTest, HostResolvedTest) {
  int no_network_max_retries = 2;
  libcurl_fetcher_.set_no_network_max_retries(no_network_max_retries);

  // This test actually sends request to internet but according to
  // https://tools.ietf.org/html/rfc2606#section-2, .invalid domain names are
  // reserved and sure to be invalid. Ideally we should mock libcurl or
  // reorganize LibcurlHttpFetcher so the part that sends request can be mocked
  // easily.
  // TODO(xiaochu) Refactor LibcurlHttpFetcher (and its relates) so it's
  // easier to mock the part that depends on internet connectivity.
  libcurl_fetcher_.BeginTransfer("https://An-uNres0lvable-uRl.invalid");

  // It's slower on Android that libcurl handle may not finish within 1 cycle.
  // Will need to wait for more cycles until it finishes. Original test didn't
  // correctly handle when we need to re-watch libcurl fds.
  while (loop_.PendingTasks() &&
         libcurl_fetcher_.GetAuxiliaryErrorCode() == ErrorCode::kSuccess) {
    loop_.RunOnce(true);
  }

  EXPECT_EQ(libcurl_fetcher_.GetAuxiliaryErrorCode(),
            ErrorCode::kUnresolvedHostError);

  // The second time, it will resolve, with error code 200 but we set the
  // download size be smaller than the transfer size so it will retry again.
  EXPECT_CALL(libcurl_fetcher_, GetHttpResponseCode())
      .WillOnce(testing::Invoke(
          [this]() { libcurl_fetcher_.http_response_code_ = 200; }))
      .WillRepeatedly(testing::Invoke(
          [this]() { libcurl_fetcher_.http_response_code_ = 0; }));
  libcurl_fetcher_.transfer_size_ = 10;

  // It's slower on Android that libcurl handle may not finish within 1 cycle.
  // Will need to wait for more cycles until it finishes. Original test didn't
  // correctly handle when we need to re-watch libcurl fds.
  while (loop_.PendingTasks() && libcurl_fetcher_.GetAuxiliaryErrorCode() ==
                                     ErrorCode::kUnresolvedHostError) {
    loop_.RunOnce(true);
  }

  EXPECT_EQ(libcurl_fetcher_.GetAuxiliaryErrorCode(),
            ErrorCode::kUnresolvedHostRecovered);

  while (loop_.PendingTasks()) {
    loop_.RunOnce(true);
  }
  // The auxilary error code should not have been changed.
  EXPECT_EQ(libcurl_fetcher_.GetAuxiliaryErrorCode(),
            ErrorCode::kUnresolvedHostRecovered);

  // If libcurl fails to resolve the name, we call res_init() to reload
  // resolv.conf and retry exactly once more. See crbug.com/982813 for details.
  EXPECT_EQ(libcurl_fetcher_.get_no_network_max_retries(),
            no_network_max_retries + 1);
}

TEST_F(LibcurlHttpFetcherTest, HttpFetcherStateMachineRetryFailedTest) {
  state_machine_.UpdateState(true);
  state_machine_.UpdateState(true);
  EXPECT_EQ(state_machine_.GetState(),
            UnresolvedHostStateMachine::State::kNotRetry);
}

TEST_F(LibcurlHttpFetcherTest, HttpFetcherStateMachineRetrySucceedTest) {
  state_machine_.UpdateState(true);
  state_machine_.UpdateState(false);
  EXPECT_EQ(state_machine_.GetState(),
            UnresolvedHostStateMachine::State::kRetriedSuccess);
}

TEST_F(LibcurlHttpFetcherTest, HttpFetcherStateMachineNoRetryTest) {
  state_machine_.UpdateState(false);
  state_machine_.UpdateState(false);
  EXPECT_EQ(state_machine_.GetState(),
            UnresolvedHostStateMachine::State::kInit);
}

}  // namespace chromeos_update_engine
