blob: d724bc420c0824c140995c18c2b3a4e5ab062aad [file] [log] [blame]
Andrew de los Reyes80061062010-02-04 14:25:00 -08001// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <sys/stat.h>
6#include <sys/types.h>
7#include <unistd.h>
8#include <algorithm>
9#include <string>
10#include <vector>
11#include <gtest/gtest.h>
12#include "update_engine/bzip_extent_writer.h"
13#include "update_engine/test_utils.h"
14#include "update_engine/utils.h"
15
16using std::min;
17using std::string;
18using std::vector;
19
20namespace chromeos_update_engine {
21
22namespace {
23const char kPathTemplate[] = "./BzipExtentWriterTest-file.XXXXXX";
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070024const uint32_t kBlockSize = 4096;
Andrew de los Reyes80061062010-02-04 14:25:00 -080025}
26
27class BzipExtentWriterTest : public ::testing::Test {
28 protected:
29 virtual void SetUp() {
30 memcpy(path_, kPathTemplate, sizeof(kPathTemplate));
31 fd_ = mkstemp(path_);
32 ASSERT_GE(fd_, 0);
33 }
34 virtual void TearDown() {
35 close(fd_);
36 LOG(INFO) << "unlink: " << path_;
37 unlink(path_);
38 }
39 int fd() { return fd_; }
40 const char* path() { return path_; }
41 void WriteAlignedExtents(size_t chunk_size, size_t first_chunk_size);
42 void TestZeroPad(bool aligned_size);
43 private:
44 int fd_;
45 char path_[sizeof(kPathTemplate)];
46};
47
48TEST_F(BzipExtentWriterTest, SimpleTest) {
49 vector<Extent> extents;
50 Extent extent;
51 extent.set_start_block(0);
52 extent.set_num_blocks(1);
53 extents.push_back(extent);
54
55 // 'echo test | bzip2 | hexdump' yields:
56 const char test_uncompressed[] = "test\n";
57 unsigned char test[] = {
58 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xcc, 0xc3,
59 0x71, 0xd4, 0x00, 0x00, 0x02, 0x41, 0x80, 0x00, 0x10, 0x02, 0x00, 0x0c,
60 0x00, 0x20, 0x00, 0x21, 0x9a, 0x68, 0x33, 0x4d, 0x19, 0x97, 0x8b, 0xb9,
61 0x22, 0x9c, 0x28, 0x48, 0x66, 0x61, 0xb8, 0xea, 0x00,
62 };
63
64 DirectExtentWriter direct_writer;
65 BzipExtentWriter bzip_writer(&direct_writer);
66 EXPECT_TRUE(bzip_writer.Init(fd(), extents, kBlockSize));
67 EXPECT_TRUE(bzip_writer.Write(test, sizeof(test)));
68 EXPECT_TRUE(bzip_writer.End());
69
70 char buf[sizeof(test_uncompressed) + 1];
71 memset(buf, 0, sizeof(buf));
72 ssize_t bytes_read = pread(fd(), buf, sizeof(buf) - 1, 0);
73 EXPECT_EQ(strlen(test_uncompressed), bytes_read);
74 EXPECT_EQ(string(buf), string(test_uncompressed));
75}
76
77TEST_F(BzipExtentWriterTest, ChunkedTest) {
78 const vector<char>::size_type kDecompressedLength = 2048 * 1024; // 2 MiB
79 const string kDecompressedPath = "BzipExtentWriterTest-file-decompressed";
80 const string kCompressedPath = "BzipExtentWriterTest-file-compressed";
81 const size_t kChunkSize = 3;
82
83 vector<Extent> extents;
84 Extent extent;
85 extent.set_start_block(0);
86 extent.set_num_blocks(kDecompressedLength / kBlockSize + 1);
87 extents.push_back(extent);
88
89 vector<char> decompressed_data(kDecompressedLength);
90 FillWithData(&decompressed_data);
91
92 EXPECT_TRUE(WriteFileVector(kDecompressedPath, decompressed_data));
93
94 EXPECT_EQ(0, System(string("cat ") + kDecompressedPath + "|bzip2>" +
95 kCompressedPath));
96
97 vector<char> compressed_data;
98 EXPECT_TRUE(utils::ReadFile(kCompressedPath, &compressed_data));
99
100 DirectExtentWriter direct_writer;
101 BzipExtentWriter bzip_writer(&direct_writer);
102 EXPECT_TRUE(bzip_writer.Init(fd(), extents, kBlockSize));
103
104 for (vector<char>::size_type i = 0; i < compressed_data.size();
105 i += kChunkSize) {
106 size_t this_chunk_size = min(kChunkSize, compressed_data.size() - i);
107 EXPECT_TRUE(bzip_writer.Write(&compressed_data[i], this_chunk_size));
108 }
109 EXPECT_TRUE(bzip_writer.End());
110
111 vector<char> output(kDecompressedLength + 1);
112 ssize_t bytes_read = pread(fd(), &output[0], output.size(), 0);
113 EXPECT_EQ(kDecompressedLength, bytes_read);
114 output.resize(kDecompressedLength);
115 ExpectVectorsEq(decompressed_data, output);
116
117 unlink(kDecompressedPath.c_str());
118 unlink(kCompressedPath.c_str());
119}
120
121} // namespace chromeos_update_engine