blob: dfecd1f540fbc218a8454fe8ea1e0f3fbe10974e [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/data_decoder/bundled_exchanges_parser_factory.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/optional.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_task_environment.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace data_decoder {
namespace {
base::FilePath GetTestFilePath(const base::FilePath& path) {
base::FilePath test_path;
base::PathService::Get(base::DIR_SOURCE_ROOT, &test_path);
test_path = test_path.Append(base::FilePath(
FILE_PATH_LITERAL("services/test/data/bundled_exchanges")));
return test_path.Append(path);
}
} // namespace
class BundledExchangesParserFactoryTest : public testing::Test {
public:
BundledExchangesParserFactoryTest()
: factory_(std::make_unique<BundledExchangesParserFactory>(
/*service_ref=*/nullptr)) {}
std::unique_ptr<mojom::BundleDataSource> CreateFileDataSource(
mojo::PendingReceiver<mojom::BundleDataSource> receiver,
base::File file) {
return factory_->CreateFileDataSourceForTesting(std::move(receiver),
std::move(file));
}
void GetParserForFile(
mojo::PendingReceiver<mojom::BundledExchangesParser> receiver,
base::File file) {
mojom::BundledExchangesParserFactory* factory = factory_.get();
return factory->GetParserForFile(std::move(receiver), std::move(file));
}
private:
std::unique_ptr<BundledExchangesParserFactory> factory_;
base::test::ScopedTaskEnvironment task_environment_;
};
TEST_F(BundledExchangesParserFactoryTest, GetSize) {
base::FilePath test_file = base::FilePath(FILE_PATH_LITERAL("hello.wbn"));
base::File file(GetTestFilePath(test_file),
base::File::FLAG_OPEN | base::File::FLAG_READ);
ASSERT_TRUE(file.IsValid());
uint64_t file_size = file.GetLength();
mojo::PendingRemote<mojom::BundleDataSource> remote;
auto data_source = CreateFileDataSource(
remote.InitWithNewPipeAndPassReceiver(), std::move(file));
uint64_t result_size;
base::RunLoop run_loop;
data_source->GetSize(
base::BindLambdaForTesting([&result_size, &run_loop](uint64_t size) {
result_size = size;
run_loop.QuitClosure().Run();
}));
run_loop.Run();
EXPECT_EQ(file_size, result_size);
}
TEST_F(BundledExchangesParserFactoryTest, Read) {
base::FilePath test_file =
GetTestFilePath(base::FilePath(FILE_PATH_LITERAL("hello.wbn")));
base::File file(test_file, base::File::FLAG_OPEN | base::File::FLAG_READ);
ASSERT_TRUE(file.IsValid());
int64_t file_length = file.GetLength();
constexpr int64_t test_length = 16;
ASSERT_LE(test_length, file_length);
std::vector<uint8_t> first16b(test_length);
ASSERT_EQ(test_length, file.Read(0, reinterpret_cast<char*>(first16b.data()),
first16b.size()));
std::vector<uint8_t> last16b(test_length);
ASSERT_EQ(test_length,
file.Read(file_length - test_length,
reinterpret_cast<char*>(last16b.data()), last16b.size()));
mojo::PendingRemote<mojom::BundleDataSource> remote;
auto data_source = CreateFileDataSource(
remote.InitWithNewPipeAndPassReceiver(), std::move(file));
base::Optional<std::vector<uint8_t>> result_data;
{
base::RunLoop run_loop;
data_source->Read(
/*offset=*/0, test_length,
base::BindLambdaForTesting(
[&result_data,
&run_loop](const base::Optional<std::vector<uint8_t>>& data) {
result_data = data;
run_loop.QuitClosure().Run();
}));
run_loop.Run();
}
ASSERT_TRUE(result_data);
EXPECT_EQ(first16b, *result_data);
{
base::RunLoop run_loop;
data_source->Read(
file_length - test_length, test_length,
base::BindLambdaForTesting(
[&result_data,
&run_loop](const base::Optional<std::vector<uint8_t>>& data) {
result_data = data;
run_loop.QuitClosure().Run();
}));
run_loop.Run();
}
ASSERT_TRUE(result_data);
EXPECT_EQ(last16b, *result_data);
{
base::RunLoop run_loop;
data_source->Read(
file_length - test_length, test_length + 1,
base::BindLambdaForTesting(
[&result_data,
&run_loop](const base::Optional<std::vector<uint8_t>>& data) {
result_data = data;
run_loop.QuitClosure().Run();
}));
run_loop.Run();
}
ASSERT_FALSE(result_data);
}
TEST_F(BundledExchangesParserFactoryTest, GetParserForFile) {
base::File file(
GetTestFilePath(base::FilePath(FILE_PATH_LITERAL("hello.wbn"))),
base::File::FLAG_OPEN | base::File::FLAG_READ);
ASSERT_TRUE(file.IsValid());
mojo::Remote<mojom::BundledExchangesParser> parser;
GetParserForFile(parser.BindNewPipeAndPassReceiver(), std::move(file));
mojom::BundleMetadataPtr metadata;
{
base::RunLoop run_loop;
parser->ParseMetadata(base::BindLambdaForTesting(
[&metadata, &run_loop](mojom::BundleMetadataPtr metadata_ptr,
const base::Optional<std::string>& error) {
metadata = std::move(metadata_ptr);
run_loop.QuitClosure().Run();
}));
run_loop.Run();
}
ASSERT_TRUE(metadata);
ASSERT_EQ(metadata->index.size(), 4u);
const auto& index = metadata->index;
std::vector<mojom::BundleResponsePtr> responses;
for (size_t i = 0; i < index.size(); i++) {
base::RunLoop run_loop;
parser->ParseResponse(
index[i]->response_offset, index[i]->response_length,
base::BindLambdaForTesting(
[&responses, &run_loop](mojom::BundleResponsePtr response,
const base::Optional<std::string>& error) {
ASSERT_TRUE(response);
ASSERT_FALSE(error);
responses.push_back(std::move(response));
run_loop.QuitClosure().Run();
}));
run_loop.Run();
}
EXPECT_EQ(index[0]->request_url, "https://test.example.org/");
EXPECT_EQ(index[0]->request_method, "GET");
EXPECT_EQ(index[0]->request_headers.size(), 0u);
EXPECT_EQ(responses[0]->response_code, 200);
EXPECT_EQ(responses[0]->response_headers["content-type"],
"text/html; charset=utf-8");
EXPECT_EQ(index[1]->request_url, "https://test.example.org/index.html");
EXPECT_EQ(index[2]->request_url,
"https://test.example.org/manifest.webmanifest");
EXPECT_EQ(index[3]->request_url, "https://test.example.org/script.js");
}
} // namespace data_decoder