blob: f1508c5ba0b52b5f81c835d71fdc30b0b9f337bb [file] [log] [blame]
// 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());
}