//
// Copyright (C) 2020 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 <unistd.h>
#include <cstdint>
#include <memory>

#include <gmock/gmock.h>
#include <gmock/gmock-actions.h>
#include <gmock/gmock-function-mocker.h>
#include <gmock/gmock-spec-builders.h>
#include <gtest/gtest.h>

#include "update_engine/common/action_pipe.h"
#include "update_engine/common/boot_control_stub.h"
#include "update_engine/common/constants.h"
#include "update_engine/common/download_action.h"
#include "update_engine/common/fake_hardware.h"
#include "update_engine/common/mock_action_processor.h"
#include "update_engine/common/mock_http_fetcher.h"
#include "update_engine/common/mock_prefs.h"
#include "update_engine/common/test_utils.h"
#include "update_engine/common/testing_constants.h"
#include "update_engine/common/utils.h"
#include "update_engine/payload_consumer/install_plan.h"
#include "update_engine/payload_consumer/payload_constants.h"
#include "update_engine/payload_generator/payload_file.h"
#include "update_engine/payload_generator/payload_signer.h"

namespace chromeos_update_engine {
using testing::_;
using testing::DoAll;
using testing::Return;
using testing::SetArgPointee;

class DownloadActionTest : public ::testing::Test {
 public:
  static constexpr int64_t METADATA_SIZE = 1024;
  static constexpr int64_t SIGNATURE_SIZE = 256;
  std::shared_ptr<ActionPipe<InstallPlan>> action_pipe{
      new ActionPipe<InstallPlan>()};
};

TEST_F(DownloadActionTest, CacheManifestInvalid) {
  std::string data(METADATA_SIZE + SIGNATURE_SIZE, '-');
  MockPrefs prefs;
  EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStatePayloadIndex, _))
      .WillRepeatedly(DoAll(SetArgPointee<1>(0L), Return(true)));
  EXPECT_CALL(prefs, GetInt64(kPrefsManifestMetadataSize, _))
      .WillRepeatedly(DoAll(SetArgPointee<1>(METADATA_SIZE), Return(true)));
  EXPECT_CALL(prefs, GetInt64(kPrefsManifestSignatureSize, _))
      .WillRepeatedly(DoAll(SetArgPointee<1>(SIGNATURE_SIZE), Return(true)));
  EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextDataOffset, _))
      .WillRepeatedly(DoAll(SetArgPointee<1>(0L), Return(true)));
  EXPECT_CALL(prefs, GetString(kPrefsManifestBytes, _))
      .WillRepeatedly(DoAll(SetArgPointee<1>(data), Return(true)));

  BootControlStub boot_control;
  MockHttpFetcher* http_fetcher = new MockHttpFetcher(data.data(), data.size());
  http_fetcher->set_delay(false);
  InstallPlan install_plan;
  auto& payload = install_plan.payloads.emplace_back();
  install_plan.download_url = "http://fake_url.invalid";
  payload.size = data.size();
  payload.payload_urls.emplace_back("http://fake_url.invalid");
  install_plan.is_resume = true;
  action_pipe->set_contents(install_plan);

  // takes ownership of passed in HttpFetcher
  auto download_action = std::make_unique<DownloadAction>(
      &prefs, &boot_control, nullptr, http_fetcher, false /* interactive */);
  download_action->set_in_pipe(action_pipe);
  MockActionProcessor mock_processor;
  download_action->SetProcessor(&mock_processor);
  download_action->PerformAction();
  ASSERT_EQ(download_action->http_fetcher()->GetBytesDownloaded(), data.size());
}

TEST_F(DownloadActionTest, CacheManifestValid) {
  // Create a valid manifest
  PayloadGenerationConfig config;
  config.version.major = kMaxSupportedMajorPayloadVersion;
  config.version.minor = kMaxSupportedMinorPayloadVersion;

  PayloadFile payload_file;
  ASSERT_TRUE(payload_file.Init(config));
  PartitionConfig partition_config{"system"};
  ScopedTempFile partition_file("part-system-XXXXXX", true);
  ftruncate(partition_file.fd(), 4096);
  partition_config.size = 4096;
  partition_config.path = partition_file.path();
  ASSERT_TRUE(payload_file.AddPartition(
      partition_config, partition_config, {}, {}, {}));
  ScopedTempFile blob_file("Blob-XXXXXX");
  ScopedTempFile manifest_file("Manifest-XXXXXX");
  uint64_t metadata_size;
  std::string private_key =
      test_utils::GetBuildArtifactsPath(kUnittestPrivateKeyPath);
  payload_file.WritePayload(
      manifest_file.path(), blob_file.path(), private_key, &metadata_size);
  uint64_t signature_blob_length = 0;
  ASSERT_TRUE(PayloadSigner::SignatureBlobLength({private_key},
                                                 &signature_blob_length));
  std::string data;
  ASSERT_TRUE(utils::ReadFile(manifest_file.path(), &data));
  data.resize(metadata_size + signature_blob_length);

  // Setup the prefs so that manifest is cached
  MockPrefs prefs;
  EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStatePayloadIndex, _))
      .WillRepeatedly(DoAll(SetArgPointee<1>(0L), Return(true)));
  EXPECT_CALL(prefs, GetInt64(kPrefsManifestMetadataSize, _))
      .WillRepeatedly(DoAll(SetArgPointee<1>(metadata_size), Return(true)));
  EXPECT_CALL(prefs, GetInt64(kPrefsManifestSignatureSize, _))
      .WillRepeatedly(
          DoAll(SetArgPointee<1>(signature_blob_length), Return(true)));
  EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextDataOffset, _))
      .WillRepeatedly(DoAll(SetArgPointee<1>(0L), Return(true)));
  EXPECT_CALL(prefs, GetString(kPrefsManifestBytes, _))
      .WillRepeatedly(DoAll(SetArgPointee<1>(data), Return(true)));
  EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextOperation, _))
      .WillRepeatedly(DoAll(SetArgPointee<1>(0), Return(true)));
  EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStatePayloadIndex, _))
      .WillRepeatedly(DoAll(SetArgPointee<1>(0), Return(true)));

  BootControlStub boot_control;
  MockHttpFetcher* http_fetcher = new MockHttpFetcher(data.data(), data.size());
  http_fetcher->set_delay(false);
  InstallPlan install_plan;
  auto& payload = install_plan.payloads.emplace_back();
  install_plan.download_url = "http://fake_url.invalid";
  payload.size = data.size();
  payload.payload_urls.emplace_back("http://fake_url.invalid");
  install_plan.is_resume = true;
  auto& install_part = install_plan.partitions.emplace_back();
  install_part.source_path = partition_file.path();
  install_part.target_path = partition_file.path();
  action_pipe->set_contents(install_plan);

  FakeHardware hardware;
  // takes ownership of passed in HttpFetcher
  auto download_action = std::make_unique<DownloadAction>(
      &prefs, &boot_control, &hardware, http_fetcher, false /* interactive */);

  auto delta_performer = std::make_unique<DeltaPerformer>(&prefs,
                                                          &boot_control,
                                                          &hardware,
                                                          nullptr,
                                                          &install_plan,
                                                          &payload,
                                                          false);
  delta_performer->set_public_key_path(kUnittestPublicKeyPath);
  download_action->SetTestFileWriter(std::move(delta_performer));
  download_action->set_in_pipe(action_pipe);
  MockActionProcessor mock_processor;
  download_action->SetProcessor(&mock_processor);
  download_action->PerformAction();

  // Manifest is cached, so no data should be downloaded from http fetcher.
  ASSERT_EQ(download_action->http_fetcher()->GetBytesDownloaded(), 0UL);
}
}  // namespace chromeos_update_engine
