blob: 1f9191c445055ab689ddc376f74965febf1ad712 [file]
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/network/public/cpp/content_decoding_util.h"
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "net/filter/filter_source_stream_test_util.h"
#include "services/network/public/cpp/basic_data_buffer_factory.h"
#include "services/network/public/cpp/data_buffer_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace network {
namespace {
// Returns the path to `services/test/data/decoder` directory.
base::FilePath GetTestDataDir() {
base::FilePath source_root;
base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &source_root);
return source_root.AppendASCII("services")
.AppendASCII("test")
.AppendASCII("data")
.AppendASCII("decoder");
}
std::string GetTestData(const std::string_view file_name) {
base::FilePath file_path = GetTestDataDir().AppendASCII(file_name);
std::string data;
CHECK(base::ReadFileToString(file_path, &data));
return data;
}
std::string GetStringFromBuffers(const DataBufferList& buffers) {
std::string decoded_string;
for (auto buffer : buffers) {
decoded_string.append(reinterpret_cast<const char*>(buffer.data()),
buffer.size());
}
return decoded_string;
}
} // namespace
TEST(ContentDecodingUtilTest, DecodeGzip) {
std::string original_data = "Hello, this is a test string to be gzipped!";
std::vector<uint8_t> compressed_data =
net::CompressGzip(original_data, /*gzip_framing=*/true);
auto factory = base::MakeRefCounted<BasicDataBufferFactory>();
auto result = ContentDecodingUtil::Decode(
compressed_data, {net::SourceStreamType::kGzip}, *factory);
ASSERT_TRUE(result);
EXPECT_EQ(GetStringFromBuffers(*result), original_data);
}
TEST(ContentDecodingUtilTest, DecodeBrotli) {
std::string compressed_data = GetTestData("google.br");
auto factory = base::MakeRefCounted<BasicDataBufferFactory>();
auto result =
ContentDecodingUtil::Decode(base::as_byte_span(compressed_data),
{net::SourceStreamType::kBrotli}, *factory);
ASSERT_TRUE(result);
EXPECT_EQ(GetStringFromBuffers(*result), GetTestData("google.txt"));
}
TEST(ContentDecodingUtilTest, DecodeZstd) {
std::string compressed_data = GetTestData("google.zst");
auto factory = base::MakeRefCounted<BasicDataBufferFactory>();
auto result =
ContentDecodingUtil::Decode(base::as_byte_span(compressed_data),
{net::SourceStreamType::kZstd}, *factory);
ASSERT_TRUE(result);
EXPECT_EQ(GetStringFromBuffers(*result), GetTestData("google.txt"));
}
TEST(ContentDecodingUtilTest, DecodeGzipLarge) {
// Create a payload larger than the buffer size (64KB).
std::string original_data;
for (int i = 0; i < 2000; ++i) {
original_data += "This is a test string to create a large payload. ";
}
std::vector<uint8_t> compressed_data =
net::CompressGzip(original_data, /*gzip_framing=*/true);
auto factory = base::MakeRefCounted<BasicDataBufferFactory>();
auto result = ContentDecodingUtil::Decode(
compressed_data, {net::SourceStreamType::kGzip}, *factory);
ASSERT_TRUE(result);
EXPECT_GT(result->size(), 1u); // Ensures multiple buffers were used
EXPECT_EQ(GetStringFromBuffers(*result), original_data);
}
TEST(ContentDecodingUtilTest, DecodeError) {
// Invalid GZIP data (not starting with gzip magic number)
std::vector<uint8_t> invalid_data = {0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07};
auto factory = base::MakeRefCounted<BasicDataBufferFactory>();
auto result = ContentDecodingUtil::Decode(
invalid_data, {net::SourceStreamType::kGzip}, *factory);
EXPECT_FALSE(result);
}
TEST(ContentDecodingUtilTest, DecodeGzipAndBrotli) {
std::string brotli_compressed_data = GetTestData("google.br");
// Gzip the brotli compressed data
std::vector<uint8_t> compressed_data =
net::CompressGzip(brotli_compressed_data, /*gzip_framing=*/true);
auto factory = base::MakeRefCounted<BasicDataBufferFactory>();
auto result = ContentDecodingUtil::Decode(
compressed_data,
{net::SourceStreamType::kBrotli, net::SourceStreamType::kGzip}, *factory);
ASSERT_TRUE(result);
EXPECT_EQ(GetStringFromBuffers(*result), GetTestData("google.txt"));
}
TEST(ContentDecodingUtilTest, DecodeDeflate) {
std::string original_data = "Hello, this is a test string to be deflated!";
std::vector<uint8_t> compressed_data =
net::CompressGzip(original_data, /*gzip_framing=*/false);
auto factory = base::MakeRefCounted<BasicDataBufferFactory>();
auto result = ContentDecodingUtil::Decode(
compressed_data, {net::SourceStreamType::kDeflate}, *factory);
ASSERT_TRUE(result);
EXPECT_EQ(GetStringFromBuffers(*result), original_data);
}
TEST(ContentDecodingUtilTest, DecodeEmptyData) {
auto factory = base::MakeRefCounted<BasicDataBufferFactory>();
auto result = ContentDecodingUtil::Decode(
base::span<const uint8_t>(), {net::SourceStreamType::kGzip}, *factory);
ASSERT_TRUE(result);
EXPECT_TRUE(result->empty());
}
} // namespace network