blob: 1389fd5d2552f6b78d61d348500afc51cc529510 [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 "content/browser/web_package/bundled_exchanges_reader.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/optional.h"
#include "base/test/scoped_task_environment.h"
#include "content/browser/web_package/bundled_exchanges_source.h"
#include "content/browser/web_package/mock_bundled_exchanges_reader_factory.h"
#include "mojo/public/c/system/data_pipe.h"
#include "services/data_decoder/public/mojom/bundled_exchanges_parser.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace content {
namespace {
class BundledExchangesReaderTest : public testing::Test {
public:
void SetUp() override {
reader_factory_ = MockBundledExchangesReaderFactory::Create();
reader_ = reader_factory_->CreateReader(body_);
}
protected:
void ReadMetadata() {
base::flat_map<GURL, data_decoder::mojom::BundleIndexValuePtr> items;
data_decoder::mojom::BundleIndexValuePtr item =
data_decoder::mojom::BundleIndexValue::New();
item->response_locations.push_back(
data_decoder::mojom::BundleResponseLocation::New(573u, 765u));
items.insert({primary_url_, std::move(item)});
data_decoder::mojom::BundleMetadataPtr metadata =
data_decoder::mojom::BundleMetadata::New(primary_url_, std::move(items),
GURL() /* manifest_url */);
reader_factory_->ReadAndFullfillMetadata(
reader_.get(), std::move(metadata),
base::BindOnce(
[](data_decoder::mojom::BundleMetadataParseErrorPtr error) {
EXPECT_FALSE(error);
}));
}
BundledExchangesReader* GetReader() { return reader_.get(); }
MockBundledExchangesReaderFactory* GetMockFactory() {
return reader_factory_.get();
}
const GURL& GetPrimaryURL() const { return primary_url_; }
const std::string& GetBody() const { return body_; }
private:
base::test::TaskEnvironment task_environment_;
std::unique_ptr<MockBundledExchangesReaderFactory> reader_factory_;
std::unique_ptr<BundledExchangesReader> reader_;
const GURL primary_url_ = GURL("https://test.example.org/");
const std::string body_ = std::string("hello new open world.");
};
TEST_F(BundledExchangesReaderTest, ReadMetadata) {
ReadMetadata();
EXPECT_EQ(GetPrimaryURL(), GetReader()->GetPrimaryURL());
EXPECT_TRUE(GetReader()->HasEntry(GetPrimaryURL()));
EXPECT_TRUE(
GetReader()->HasEntry(GURL("https://user:pass@test.example.org/")));
EXPECT_TRUE(GetReader()->HasEntry(GURL("https://test.example.org/#ref")));
EXPECT_FALSE(GetReader()->HasEntry(GURL("https://test.example.org/404")));
}
TEST_F(BundledExchangesReaderTest, ReadResponse) {
ReadMetadata();
ASSERT_TRUE(GetReader()->HasEntry(GetPrimaryURL()));
data_decoder::mojom::BundleResponsePtr response =
data_decoder::mojom::BundleResponse::New();
response->response_code = 200;
response->payload_offset = 0xdead;
response->payload_length = 0xbeaf;
GetMockFactory()->ReadAndFullfillResponse(
GetReader(), GetPrimaryURL(), std::move(response),
base::BindOnce([](data_decoder::mojom::BundleResponsePtr response) {
EXPECT_TRUE(response);
if (response) {
EXPECT_EQ(200, response->response_code);
EXPECT_EQ(0xdeadu, response->payload_offset);
EXPECT_EQ(0xbeafu, response->payload_length);
}
}));
}
TEST_F(BundledExchangesReaderTest, ReadResponseForURLContainingUserAndPass) {
GURL url = GURL("https://user:pass@test.example.org/");
ReadMetadata();
ASSERT_TRUE(GetReader()->HasEntry(url));
data_decoder::mojom::BundleResponsePtr response =
data_decoder::mojom::BundleResponse::New();
response->response_code = 200;
response->payload_offset = 0xdead;
response->payload_length = 0xbeaf;
GetMockFactory()->ReadAndFullfillResponse(
GetReader(), url, std::move(response),
base::BindOnce([](data_decoder::mojom::BundleResponsePtr response) {
EXPECT_TRUE(response);
if (response) {
EXPECT_EQ(200, response->response_code);
EXPECT_EQ(0xdeadu, response->payload_offset);
EXPECT_EQ(0xbeafu, response->payload_length);
}
}));
}
TEST_F(BundledExchangesReaderTest, ReadResponseForURLContainingFragment) {
GURL url = GURL("https://test.example.org/#fragment");
ReadMetadata();
ASSERT_TRUE(GetReader()->HasEntry(url));
data_decoder::mojom::BundleResponsePtr response =
data_decoder::mojom::BundleResponse::New();
response->response_code = 200;
response->payload_offset = 0xdead;
response->payload_length = 0xbeaf;
GetMockFactory()->ReadAndFullfillResponse(
GetReader(), url, std::move(response),
base::BindOnce([](data_decoder::mojom::BundleResponsePtr response) {
EXPECT_TRUE(response);
if (response) {
EXPECT_EQ(200, response->response_code);
EXPECT_EQ(0xdeadu, response->payload_offset);
EXPECT_EQ(0xbeafu, response->payload_length);
}
}));
}
TEST_F(BundledExchangesReaderTest, ReadResponseBody) {
ReadMetadata();
data_decoder::mojom::BundleResponsePtr response =
data_decoder::mojom::BundleResponse::New();
constexpr size_t expected_offset = 4;
const size_t expected_length = GetBody().size() - 8;
response->payload_offset = expected_offset;
response->payload_length = expected_length;
mojo::ScopedDataPipeProducerHandle producer;
mojo::ScopedDataPipeConsumerHandle consumer;
MojoCreateDataPipeOptions options;
options.struct_size = sizeof(MojoCreateDataPipeOptions);
options.element_num_bytes = 1;
options.capacity_num_bytes = response->payload_length + 1;
ASSERT_EQ(MOJO_RESULT_OK,
mojo::CreateDataPipe(&options, &producer, &consumer));
base::RunLoop run_loop;
MojoResult callback_result;
GetReader()->ReadResponseBody(
std::move(response), std::move(producer),
base::BindOnce(
[](base::Closure quit_closure, MojoResult* callback_result,
MojoResult result) {
*callback_result = result;
std::move(quit_closure).Run();
},
run_loop.QuitClosure(), &callback_result));
run_loop.Run();
ASSERT_EQ(MOJO_RESULT_OK, callback_result);
std::vector<char> buffer(expected_length);
uint32_t bytes_read = buffer.size();
MojoResult read_result =
consumer->ReadData(buffer.data(), &bytes_read, /*flags=*/0);
ASSERT_EQ(MOJO_RESULT_OK, read_result);
ASSERT_EQ(buffer.size(), bytes_read);
EXPECT_EQ(GetBody().substr(expected_offset, expected_length),
std::string(buffer.data(), bytes_read));
}
} // namespace
} // namespace content