// Copyright (c) 2012 The Chromium OS 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 <ext2fs/ext2fs.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <string>
#include <vector>

#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <gtest/gtest.h>

#include "update_engine/payload_generator/delta_diff_generator.h"
#include "update_engine/payload_generator/graph_types.h"
#include "update_engine/payload_generator/metadata.h"
#include "update_engine/test_utils.h"
#include "update_engine/utils.h"

using std::string;
using std::vector;

namespace chromeos_update_engine {

typedef DeltaDiffGenerator::Block Block;

class MetadataTest : public ::testing::Test {
};

TEST_F(MetadataTest, RunAsRootReadMetadataDissimilarFileSystems) {
  string a_img, b_img;
  EXPECT_TRUE(utils::MakeTempFile("a_img.XXXXXX", &a_img, nullptr));
  ScopedPathUnlinker a_img_unlinker(a_img);
  EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &b_img, nullptr));
  ScopedPathUnlinker b_img_unlinker(b_img);

  CreateEmptyExtImageAtPath(a_img, 10485759, 4096);
  CreateEmptyExtImageAtPath(b_img, 11534336, 4096);

  Graph graph;
  vector<Block> blocks;
  EXPECT_TRUE(Metadata::DeltaReadMetadata(&graph,
                                          &blocks,
                                          a_img,
                                          b_img,
                                          0,
                                          nullptr));
  EXPECT_EQ(graph.size(), 0);

  CreateEmptyExtImageAtPath(a_img, 10485759, 4096);
  CreateEmptyExtImageAtPath(b_img, 10485759, 8192);

  graph.clear();
  blocks.clear();
  EXPECT_TRUE(Metadata::DeltaReadMetadata(&graph,
                                          &blocks,
                                          a_img,
                                          b_img,
                                          0,
                                          nullptr));
  EXPECT_EQ(graph.size(), 0);
}

TEST_F(MetadataTest, RunAsRootReadMetadata) {
  string a_img, b_img, data_file;
  EXPECT_TRUE(utils::MakeTempFile("a_img.XXXXXX", &a_img, nullptr));
  ScopedPathUnlinker a_img_unlinker(a_img);
  EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &b_img, nullptr));
  ScopedPathUnlinker b_img_unlinker(b_img);
  EXPECT_TRUE(utils::MakeTempFile("data_file.XXXXXX", &data_file, nullptr));
  ScopedPathUnlinker data_file_unlinker(data_file);

  const size_t image_size = (256 * 1024 * 1024);  // Enough for 2 block groups
  const int block_size = 4096;
  CreateEmptyExtImageAtPath(a_img, image_size, block_size);

  // Create a file large enough to create an indirect block
  {
    string a_img_mnt;
    ScopedLoopMounter a_img_mount(a_img, &a_img_mnt, 0);
    System(base::StringPrintf("dd if=/dev/zero of=%s/test_file bs=%d count=%d",
                              a_img_mnt.c_str(), block_size,
                              EXT2_NDIR_BLOCKS + 1));
  }

  System(base::StringPrintf("cp %s %s", a_img.c_str(), b_img.c_str()));

  int fd = open(data_file.c_str(), O_RDWR | O_CREAT, S_IRWXU);
  EXPECT_NE(fd, -1);
  ScopedFdCloser fd_closer(&fd);

  Graph graph;
  vector<Block> blocks(image_size / block_size);
  off_t data_file_size;
  EXPECT_TRUE(Metadata::DeltaReadMetadata(&graph,
                                          &blocks,
                                          a_img,
                                          b_img,
                                          fd,
                                          &data_file_size));

  // There are 12 metadata that we look for:
  //   - Block group 0 metadata (superblock, group descriptor, bitmaps, etc)
  //       - Chunk 0, 1, 2, 3
  //   - Block group 1 metadata
  //       - Chunk 0, 1, 2, 3
  //   - Root directory (inode 2)
  //   - Journal (inode 8)
  //   - lost+found directory (inode 11)
  //   - test_file indirect block (inode 12)
  struct {
    string metadata_name;
    off_t start_block;  // Set to -1 to skip start block verification
    off_t num_blocks;   // Set to -1 to skip num blocks verification
  } exp_results[] =
      {{"<rootfs-bg-0-0-metadata>", 0, 104},
       {"<rootfs-bg-0-1-metadata>", 104, 104},
       {"<rootfs-bg-0-2-metadata>", 208, 104},
       {"<rootfs-bg-0-3-metadata>", 312, 104},
       {"<rootfs-bg-0-4-metadata>", 416, 104},
       {"<rootfs-bg-0-5-metadata>", 520, 104},
       {"<rootfs-bg-0-6-metadata>", 624, 104},
       {"<rootfs-bg-0-7-metadata>", 728, 104},
       {"<rootfs-bg-0-8-metadata>", 832, 104},
       {"<rootfs-bg-0-9-metadata>", 936, 107},
       {"<rootfs-bg-1-0-metadata>", 32768, 104},
       {"<rootfs-bg-1-1-metadata>", 32872, 104},
       {"<rootfs-bg-1-2-metadata>", 32976, 104},
       {"<rootfs-bg-1-3-metadata>", 33080, 104},
       {"<rootfs-bg-1-4-metadata>", 33184, 104},
       {"<rootfs-bg-1-5-metadata>", 33288, 104},
       {"<rootfs-bg-1-6-metadata>", 33392, 104},
       {"<rootfs-bg-1-7-metadata>", 33496, 104},
       {"<rootfs-bg-1-8-metadata>", 33600, 104},
       {"<rootfs-bg-1-9-metadata>", 33704, 107},
       {"<rootfs-inode-2-metadata>", -1, 1},
       {"<rootfs-inode-8-metadata>", -1, 4101},
       {"<rootfs-inode-11-metadata>", -1, 4},
       {"<rootfs-inode-12-metadata>", -1, 1}};

  int num_exp_results = sizeof(exp_results) / sizeof(exp_results[0]);
  EXPECT_EQ(graph.size(), num_exp_results);

  for (int i = 0; i < num_exp_results; i++) {
    Vertex& vertex = graph[i];
    DeltaArchiveManifest_InstallOperation& op = vertex.op;

    EXPECT_STRCASEEQ(vertex.file_name.c_str(),
                     exp_results[i].metadata_name.c_str());

    EXPECT_EQ(op.src_extents().size(), op.dst_extents().size());
    for (int e = 0; e < op.src_extents().size(); e++) {
      EXPECT_EQ(op.src_extents(e).start_block(),
                op.dst_extents(e).start_block());
      EXPECT_EQ(op.src_extents(e).num_blocks(),
                op.dst_extents(e).num_blocks());
    }

    if (exp_results[i].start_block != -1) {
      EXPECT_EQ(op.src_extents(0).start_block(), exp_results[i].start_block);
    }

    if (exp_results[i].num_blocks != -1) {
      EXPECT_EQ(op.src_extents(0).num_blocks(), exp_results[i].num_blocks);
    }
  }
}

}  // namespace chromeos_update_engine
