910e62b5创建于 1月15日历史提交
// 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/compiler_specific.h"
#include "base/files/file.h"
#include "base/files/file_path.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 std::optional<size_t> bytes_read =
        src_file.ReadAtCurrentPos(tar_buffer);
    ASSERT_TRUE(bytes_read.has_value());
    ASSERT_GE(*bytes_read, 0u);

    base::span<const uint8_t> bin_buffer;
    tar_reader.ExtractChunk(base::span(tar_buffer).first(*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 std::optional<size_t> bytes_read =
      src_file.ReadAtCurrentPos(tar_buffer);
  ASSERT_TRUE(bytes_read.has_value());
  ASSERT_GE(*bytes_read, 0u);

  base::span<const uint8_t> bin_buffer;
  tar_reader.ExtractChunk(base::span(tar_buffer).first(*bytes_read),
                          bin_buffer);

  EXPECT_TRUE(tar_reader.IsComplete());
}