blob: a1f3e4842039a2b5b8130693069b8e1f45c9667c [file] [log] [blame]
// 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 <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string>
#include <vector>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <gtest/gtest.h>
#include "update_engine/graph_types.h"
#include "update_engine/delta_diff_generator.h"
#include "update_engine/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, NULL));
ScopedPathUnlinker a_img_unlinker(a_img);
EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &b_img, NULL));
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,
NULL));
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,
NULL));
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, NULL));
ScopedPathUnlinker a_img_unlinker(a_img);
EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &b_img, NULL));
ScopedPathUnlinker b_img_unlinker(b_img);
EXPECT_TRUE(utils::MakeTempFile("data_file.XXXXXX", &data_file, NULL));
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