1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2009 The Android Open Source Project 3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License"); 5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License. 6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at 7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// http://www.apache.org/licenses/LICENSE-2.0 9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software 11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS, 12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and 14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License. 15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 168006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes 1739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/payload_consumer/bzip_extent_writer.h" 18aab50e31f0b80ed53a9b8d5dbabcf943974bd32cAlex Deymo 194eccae2ffd51c1e76ccd6463212c8e3addbb873eXiyuan Xia#include <fcntl.h> 204eccae2ffd51c1e76ccd6463212c8e3addbb873eXiyuan Xia 218006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes#include <algorithm> 228006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes#include <string> 238006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes#include <vector> 2405322879380a15f7042f4023b4ce4fec4b8bf50bAlex Deymo 253f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/make_unique_ptr.h> 268006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes#include <gtest/gtest.h> 2705322879380a15f7042f4023b4ce4fec4b8bf50bAlex Deymo 2839910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/test_utils.h" 2939910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/utils.h" 308006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes 318006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyesusing std::min; 328006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyesusing std::string; 338006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyesusing std::vector; 348006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes 358006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyesnamespace chromeos_update_engine { 368006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes 378006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyesnamespace { 3809e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyesconst uint32_t kBlockSize = 4096; 398006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes} 408006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes 418006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyesclass BzipExtentWriterTest : public ::testing::Test { 428006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes protected: 43610277efc6f7e5239158dfa4bb3b1021804326e0Alex Deymo void SetUp() override { 44f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen fd_.reset(new EintrSafeFileDescriptor); 45bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo ASSERT_TRUE(fd_->Open(temp_file_.path().c_str(), O_RDWR, 0600)); 468006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes } 47610277efc6f7e5239158dfa4bb3b1021804326e0Alex Deymo void TearDown() override { 48f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen fd_->Close(); 498006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes } 508006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes void WriteAlignedExtents(size_t chunk_size, size_t first_chunk_size); 518006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes void TestZeroPad(bool aligned_size); 52f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen 53f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen FileDescriptorPtr fd_; 54bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo test_utils::ScopedTempFile temp_file_{"BzipExtentWriterTest-file.XXXXXX"}; 558006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes}; 568006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes 578006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los ReyesTEST_F(BzipExtentWriterTest, SimpleTest) { 588006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes vector<Extent> extents; 598006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes Extent extent; 608006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes extent.set_start_block(0); 618006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes extent.set_num_blocks(1); 628006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes extents.push_back(extent); 638006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes 648006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes // 'echo test | bzip2 | hexdump' yields: 65e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov static const char test_uncompressed[] = "test\n"; 66f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko static const uint8_t test[] = { 678006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xcc, 0xc3, 688006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes 0x71, 0xd4, 0x00, 0x00, 0x02, 0x41, 0x80, 0x00, 0x10, 0x02, 0x00, 0x0c, 698006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes 0x00, 0x20, 0x00, 0x21, 0x9a, 0x68, 0x33, 0x4d, 0x19, 0x97, 0x8b, 0xb9, 70e1d1e98ef34337645a6d10551c2b0485340e3d8cGilad Arnold 0x22, 0x9c, 0x28, 0x48, 0x66, 0x61, 0xb8, 0xea, 0x00, 718006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes }; 72e1d1e98ef34337645a6d10551c2b0485340e3d8cGilad Arnold 7305322879380a15f7042f4023b4ce4fec4b8bf50bAlex Deymo BzipExtentWriter bzip_writer( 743f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko brillo::make_unique_ptr(new DirectExtentWriter())); 75f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen EXPECT_TRUE(bzip_writer.Init(fd_, extents, kBlockSize)); 768006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes EXPECT_TRUE(bzip_writer.Write(test, sizeof(test))); 778006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes EXPECT_TRUE(bzip_writer.End()); 78e1d1e98ef34337645a6d10551c2b0485340e3d8cGilad Arnold 793f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko brillo::Blob buf; 80bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo EXPECT_TRUE(utils::ReadFile(temp_file_.path(), &buf)); 81f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen EXPECT_EQ(strlen(test_uncompressed), buf.size()); 82f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko EXPECT_EQ(string(buf.begin(), buf.end()), string(test_uncompressed)); 838006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes} 848006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes 858006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los ReyesTEST_F(BzipExtentWriterTest, ChunkedTest) { 86bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo // Generated with: 874eccae2ffd51c1e76ccd6463212c8e3addbb873eXiyuan Xia // yes "ABC" | head -c 819200 | bzip2 -9 | 884eccae2ffd51c1e76ccd6463212c8e3addbb873eXiyuan Xia // hexdump -v -e '" " 11/1 "0x%02x, " "\n"' 89bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo static const uint8_t kCompressedData[] = { 90bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xbe, 91bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo 0x1c, 0xda, 0xee, 0x03, 0x1f, 0xff, 0xc4, 0x00, 0x00, 0x10, 0x38, 92bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo 0x00, 0x20, 0x00, 0x50, 0x66, 0x9a, 0x05, 0x28, 0x38, 0x00, 0x11, 93bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo 0x60, 0x00, 0x22, 0xd0, 0x00, 0x45, 0xc0, 0x00, 0x8b, 0xc5, 0xdc, 94bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo 0x91, 0x4e, 0x14, 0x24, 0x2f, 0x87, 0x36, 0xbb, 0x80}; 95bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo brillo::Blob compressed_data(std::begin(kCompressedData), 96bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo std::end(kCompressedData)); 97bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo 98bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo const brillo::Blob::size_type kDecompressedLength = 800 * 1024; // 800 KiB 998006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes const size_t kChunkSize = 3; 100e1d1e98ef34337645a6d10551c2b0485340e3d8cGilad Arnold 101bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo brillo::Blob decompressed_data(kDecompressedLength); 102bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo for (size_t i = 0; i < decompressed_data.size(); ++i) 103bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo decompressed_data[i] = static_cast<uint8_t>("ABC\n"[i % 4]); 104bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo 1058006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes vector<Extent> extents; 1068006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes Extent extent; 1078006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes extent.set_start_block(0); 108bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo extent.set_num_blocks((kDecompressedLength + kBlockSize - 1) / kBlockSize); 1098006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes extents.push_back(extent); 1108006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes 11105322879380a15f7042f4023b4ce4fec4b8bf50bAlex Deymo BzipExtentWriter bzip_writer( 1123f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko brillo::make_unique_ptr(new DirectExtentWriter())); 113f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen EXPECT_TRUE(bzip_writer.Init(fd_, extents, kBlockSize)); 1148006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes 1153f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko brillo::Blob original_compressed_data = compressed_data; 1163f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko for (brillo::Blob::size_type i = 0; i < compressed_data.size(); 1178006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes i += kChunkSize) { 1188006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes size_t this_chunk_size = min(kChunkSize, compressed_data.size() - i); 1198006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes EXPECT_TRUE(bzip_writer.Write(&compressed_data[i], this_chunk_size)); 1208006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes } 1218006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes EXPECT_TRUE(bzip_writer.End()); 122e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov 123e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov // Check that the const input has not been clobbered. 12410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo test_utils::ExpectVectorsEq(original_compressed_data, compressed_data); 125e1d1e98ef34337645a6d10551c2b0485340e3d8cGilad Arnold 1263f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko brillo::Blob output; 127bffa06080ec8bd5d196cbfadf2023f78b6e89169Alex Deymo EXPECT_TRUE(utils::ReadFile(temp_file_.path(), &output)); 128f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen EXPECT_EQ(kDecompressedLength, output.size()); 12910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo test_utils::ExpectVectorsEq(decompressed_data, output); 1308006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes} 1318006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes 1328006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes} // namespace chromeos_update_engine 133