//
// Copyright (C) 2010 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/payload_generator/full_update_generator.h"

#include <string>
#include <vector>

#include <gtest/gtest.h>

#include "update_engine/common/test_utils.h"
#include "update_engine/payload_consumer/payload_constants.h"
#include "update_engine/payload_generator/extent_utils.h"

using chromeos_update_engine::test_utils::FillWithData;
using std::string;
using std::vector;

namespace chromeos_update_engine {

class FullUpdateGeneratorTest : public ::testing::Test {
 protected:
  void SetUp() override {
    config_.is_delta = false;
    config_.minor_version = kFullPayloadMinorVersion;
    config_.hard_chunk_size = 128 * 1024;
    config_.block_size = 4096;

    EXPECT_TRUE(utils::MakeTempFile("FullUpdateTest_partition.XXXXXX",
                                    &new_part_conf.path,
                                    nullptr));
    EXPECT_TRUE(utils::MakeTempFile("FullUpdateTest_blobs.XXXXXX",
                                    &out_blobs_path_,
                                    &out_blobs_fd_));

    blob_file_.reset(new BlobFileWriter(out_blobs_fd_, &out_blobs_length_));
    part_path_unlinker_.reset(new ScopedPathUnlinker(new_part_conf.path));
    out_blobs_unlinker_.reset(new ScopedPathUnlinker(out_blobs_path_));
  }

  PayloadGenerationConfig config_;
  PartitionConfig new_part_conf{"part"};

  vector<AnnotatedOperation> aops;

  // Output file holding the payload blobs.
  string out_blobs_path_;
  int out_blobs_fd_{-1};
  off_t out_blobs_length_{0};
  ScopedFdCloser out_blobs_fd_closer_{&out_blobs_fd_};

  std::unique_ptr<BlobFileWriter> blob_file_;
  std::unique_ptr<ScopedPathUnlinker> part_path_unlinker_;
  std::unique_ptr<ScopedPathUnlinker> out_blobs_unlinker_;

  // FullUpdateGenerator under test.
  FullUpdateGenerator generator_;
};

TEST_F(FullUpdateGeneratorTest, RunTest) {
  brillo::Blob new_part(9 * 1024 * 1024);
  FillWithData(&new_part);
  new_part_conf.size = new_part.size();

  EXPECT_TRUE(test_utils::WriteFileVector(new_part_conf.path, new_part));

  EXPECT_TRUE(generator_.GenerateOperations(config_,
                                            new_part_conf,  // this is ignored
                                            new_part_conf,
                                            blob_file_.get(),
                                            &aops));
  int64_t new_part_chunks = new_part_conf.size / config_.hard_chunk_size;
  EXPECT_EQ(new_part_chunks, static_cast<int64_t>(aops.size()));
  for (off_t i = 0; i < new_part_chunks; ++i) {
    EXPECT_EQ(1, aops[i].op.dst_extents_size());
    EXPECT_EQ(static_cast<uint64_t>(i * config_.hard_chunk_size / config_.block_size),
              aops[i].op.dst_extents(0).start_block()) << "i = " << i;
    EXPECT_EQ(config_.hard_chunk_size / config_.block_size,
              aops[i].op.dst_extents(0).num_blocks());
    if (aops[i].op.type() != InstallOperation::REPLACE) {
      EXPECT_EQ(InstallOperation::REPLACE_BZ, aops[i].op.type());
    }
  }
}

// Test that if the chunk size is not a divisor of the image size, it handles
// correctly the last chunk of the partition.
TEST_F(FullUpdateGeneratorTest, ChunkSizeTooBig) {
  config_.hard_chunk_size = 1024 * 1024;
  config_.soft_chunk_size = config_.hard_chunk_size;
  brillo::Blob new_part(1536 * 1024);  // 1.5 MiB
  new_part_conf.size = new_part.size();

  EXPECT_TRUE(test_utils::WriteFileVector(new_part_conf.path, new_part));

  EXPECT_TRUE(generator_.GenerateOperations(config_,
                                            new_part_conf,  // this is ignored
                                            new_part_conf,
                                            blob_file_.get(),
                                            &aops));
  // new_part has one chunk and a half.
  EXPECT_EQ(2U, aops.size());
  EXPECT_EQ(config_.hard_chunk_size / config_.block_size,
            BlocksInExtents(aops[0].op.dst_extents()));
  EXPECT_EQ((new_part.size() - config_.hard_chunk_size) / config_.block_size,
            BlocksInExtents(aops[1].op.dst_extents()));
}

// Test that if the image size is much smaller than the chunk size, it handles
// correctly the only chunk of the partition.
TEST_F(FullUpdateGeneratorTest, ImageSizeTooSmall) {
  brillo::Blob new_part(16 * 1024);
  new_part_conf.size = new_part.size();

  EXPECT_TRUE(test_utils::WriteFileVector(new_part_conf.path, new_part));

  EXPECT_TRUE(generator_.GenerateOperations(config_,
                                            new_part_conf,  // this is ignored
                                            new_part_conf,
                                            blob_file_.get(),
                                            &aops));

  // new_part has less than one chunk.
  EXPECT_EQ(1U, aops.size());
  EXPECT_EQ(new_part.size() / config_.block_size,
            BlocksInExtents(aops[0].op.dst_extents()));
}

}  // namespace chromeos_update_engine
