| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/services/file_util/single_file_tar_reader.h" |
| |
| #include <memory> |
| #include <vector> |
| |
| #include "base/files/file_path.h" |
| #include "base/files/file_util.h" |
| #include "base/numerics/safe_conversions.h" |
| #include "base/path_service.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| constexpr int kTarBufferSize = 8192; |
| |
| class SingleFileTarReaderTest : public testing::Test { |
| public: |
| SingleFileTarReaderTest() = default; |
| SingleFileTarReaderTest(const SingleFileTarReaderTest&) = delete; |
| SingleFileTarReaderTest& operator=(const SingleFileTarReaderTest&) = delete; |
| ~SingleFileTarReaderTest() override = default; |
| |
| base::FilePath GetFilePath(const char* file_name) { |
| base::FilePath test_data; |
| EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data)); |
| return test_data.AppendASCII("image_writer_private").AppendASCII(file_name); |
| } |
| }; |
| |
| TEST_F(SingleFileTarReaderTest, ExtractTarFile) { |
| base::FilePath path; |
| ASSERT_NO_FATAL_FAILURE(path = GetFilePath("test.tar")); |
| base::File src_file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); |
| |
| SingleFileTarReader tar_reader; |
| std::vector<uint8_t> tar_buffer(kTarBufferSize); |
| std::vector<uint8_t> contents; |
| while (!tar_reader.IsComplete()) { |
| const int bytes_read = src_file.ReadAtCurrentPos( |
| reinterpret_cast<char*>(tar_buffer.data()), tar_buffer.size()); |
| ASSERT_GE(bytes_read, 0); |
| |
| base::span<const uint8_t> bin_buffer; |
| tar_reader.ExtractChunk( |
| base::span(tar_buffer).first(base::checked_cast<size_t>(bytes_read)), |
| bin_buffer); |
| contents.insert(contents.begin(), bin_buffer.begin(), bin_buffer.end()); |
| } |
| |
| EXPECT_EQ(4u, tar_reader.tar_content_size()); |
| EXPECT_EQ(4u, tar_reader.bytes_processed()); |
| // Generated by echo foo | xxd --include |
| EXPECT_EQ((std::vector<uint8_t>{0x66, 0x6f, 0x6f, 0x0a}), contents); |
| } |
| |
| TEST_F(SingleFileTarReaderTest, ReadOctalNumber) { |
| // Test the common case of null-terminated octal ASCII number. |
| // Generated by echo -en '00000000123\x00' | xxd --include |
| const std::vector<uint8_t> kNumber{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, |
| 0x30, 0x30, 0x31, 0x32, 0x33, 0x00}; |
| EXPECT_EQ(83u, SingleFileTarReader::ReadOctalNumber(kNumber)); |
| |
| // Test the case of big-endian integer with padding. |
| // 20bc13a00(16) = 8787147264(10) |
| const std::vector<uint8_t> kBigNumber{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x02, 0x0b, 0xc1, 0x3a, 0x00}; |
| EXPECT_EQ(8787147264u, SingleFileTarReader::ReadOctalNumber(kBigNumber)); |
| |
| // Test if ReadOctalNumber return null when the input is shorter than 8 bytes. |
| const std::vector<uint8_t> kShortNumber{0x30, 0x30, 0x30, 0x30, 0x30, 0x30}; |
| EXPECT_TRUE(!SingleFileTarReader::ReadOctalNumber(kShortNumber).has_value()); |
| } |
| |
| TEST_F(SingleFileTarReaderTest, EmptyFile) { |
| // Use a .tar file containing an empty file. |
| base::FilePath path; |
| ASSERT_NO_FATAL_FAILURE(path = GetFilePath("empty_file.tar")); |
| base::File src_file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); |
| |
| SingleFileTarReader tar_reader; |
| std::vector<uint8_t> tar_buffer(kTarBufferSize); |
| const int bytes_read = src_file.ReadAtCurrentPos( |
| reinterpret_cast<char*>(tar_buffer.data()), tar_buffer.size()); |
| ASSERT_GE(bytes_read, 0); |
| |
| base::span<const uint8_t> bin_buffer; |
| tar_reader.ExtractChunk( |
| base::span(tar_buffer).first(base::checked_cast<size_t>(bytes_read)), |
| bin_buffer); |
| |
| EXPECT_TRUE(tar_reader.IsComplete()); |
| } |