
In a future commit, this code will be re-used in the implementation of an in-renderer resource loader, which will not be located in //content/browser. Bug: 362511750 Change-Id: I58432846087a05fe165e3443d5f33d119a05d750 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6033036 Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com> Reviewed-by: Alex Moshchuk <alexmos@chromium.org> Commit-Queue: Alex Yang <aycyang@chromium.org> Cr-Commit-Position: refs/heads/main@{#1385832}
144 lines
4.9 KiB
C++
144 lines
4.9 KiB
C++
// Copyright 2024 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "content/common/web_ui_loading_util.h"
|
|
|
|
#include <cstdint>
|
|
#include <optional>
|
|
#include <vector>
|
|
|
|
#include "base/containers/span.h"
|
|
#include "base/memory/ref_counted_memory.h"
|
|
#include "base/memory/scoped_refptr.h"
|
|
#include "base/test/task_environment.h"
|
|
#include "base/types/expected.h"
|
|
#include "mojo/public/c/system/data_pipe.h"
|
|
#include "mojo/public/c/system/types.h"
|
|
#include "net/base/net_errors.h"
|
|
#include "net/http/http_byte_range.h"
|
|
#include "net/http/http_request_headers.h"
|
|
#include "services/network/public/mojom/url_response_head.mojom.h"
|
|
#include "services/network/test/test_url_loader_client.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
namespace content {
|
|
|
|
namespace webui {
|
|
|
|
namespace {
|
|
|
|
struct RangeTestCase {
|
|
std::optional<std::string> range;
|
|
std::optional<GetRequestedRangeError> error;
|
|
};
|
|
|
|
struct SendDataTestCase {
|
|
std::optional<net::HttpByteRange> range;
|
|
std::string data;
|
|
base::expected<std::string, int> result;
|
|
};
|
|
|
|
class WebUILoadingUtilGetRequestedRangeTest
|
|
: public ::testing::TestWithParam<RangeTestCase> {};
|
|
class WebUILoadingUtilSendDataTest
|
|
: public ::testing::TestWithParam<SendDataTestCase> {
|
|
private:
|
|
// For TestURLLoaderClient.
|
|
base::test::TaskEnvironment task_environment_;
|
|
};
|
|
|
|
std::optional<std::string> ReadAllData(network::TestURLLoaderClient& client) {
|
|
size_t response_size;
|
|
MojoResult result;
|
|
result = client.response_body().ReadData(
|
|
MOJO_READ_DATA_FLAG_QUERY, base::span<uint8_t>(), response_size);
|
|
if (result != MOJO_RESULT_OK) {
|
|
return std::nullopt;
|
|
}
|
|
std::vector<uint8_t> response_bytes(response_size);
|
|
result = client.response_body().ReadData(MOJO_READ_DATA_FLAG_ALL_OR_NONE,
|
|
response_bytes, response_size);
|
|
if (result != MOJO_RESULT_OK) {
|
|
return std::nullopt;
|
|
}
|
|
std::string response_body(response_bytes.begin(), response_bytes.end());
|
|
return std::make_optional(response_body);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST_P(WebUILoadingUtilGetRequestedRangeTest, GetRequestedRange) {
|
|
net::HttpRequestHeaders headers;
|
|
if (GetParam().range) {
|
|
headers.SetHeader(net::HttpRequestHeaders::kRange, *GetParam().range);
|
|
}
|
|
base::expected<net::HttpByteRange, GetRequestedRangeError> result =
|
|
GetRequestedRange(headers);
|
|
if (GetParam().error) {
|
|
EXPECT_FALSE(result.has_value());
|
|
EXPECT_EQ(result.error(), *GetParam().error);
|
|
} else {
|
|
EXPECT_TRUE(result.has_value());
|
|
}
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
WebUILoadingUtilGetRequestedRangeTest,
|
|
WebUILoadingUtilGetRequestedRangeTest,
|
|
::testing::Values(
|
|
RangeTestCase(std::nullopt,
|
|
std::make_optional(GetRequestedRangeError::kNoRanges)),
|
|
RangeTestCase(std::make_optional("bytes=1-9"), std::nullopt),
|
|
RangeTestCase(
|
|
std::make_optional("bytes=1-9,11-19"),
|
|
std::make_optional(GetRequestedRangeError::kMultipleRanges)),
|
|
RangeTestCase(std::make_optional("bytes=3-2"),
|
|
std::make_optional(GetRequestedRangeError::kParseFailed)),
|
|
RangeTestCase(
|
|
std::make_optional("byt"),
|
|
std::make_optional(GetRequestedRangeError::kParseFailed))));
|
|
|
|
TEST_P(WebUILoadingUtilSendDataTest, SendData) {
|
|
network::TestURLLoaderClient client;
|
|
auto url_response_head = network::mojom::URLResponseHead::New();
|
|
const scoped_refptr<base::RefCountedString> data =
|
|
base::MakeRefCounted<base::RefCountedString>(GetParam().data);
|
|
const bool success = SendData(std::move(url_response_head),
|
|
client.CreateRemote(), GetParam().range, data);
|
|
client.RunUntilComplete();
|
|
// If an error is expected, verify the status error code is correct and
|
|
// terminate the test early.
|
|
if (!GetParam().result.has_value()) {
|
|
EXPECT_FALSE(success);
|
|
EXPECT_EQ(GetParam().result.error(), client.completion_status().error_code);
|
|
return;
|
|
}
|
|
// No error expected. Verify response body is correct.
|
|
EXPECT_TRUE(success);
|
|
EXPECT_EQ(net::OK, client.completion_status().error_code);
|
|
ASSERT_TRUE(client.response_body().is_valid());
|
|
std::optional<std::string> response_body = ReadAllData(client);
|
|
ASSERT_TRUE(response_body);
|
|
EXPECT_EQ(GetParam().result.value(), *response_body);
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
WebUILoadingUtilSendDataTest,
|
|
WebUILoadingUtilSendDataTest,
|
|
::testing::Values(
|
|
SendDataTestCase(std::nullopt,
|
|
"this is some data",
|
|
"this is some data"),
|
|
SendDataTestCase(std::make_optional(net::HttpByteRange::Bounded(3, 8)),
|
|
"this is some data",
|
|
"s is s"),
|
|
SendDataTestCase(
|
|
std::make_optional(net::HttpByteRange::Bounded(3, 2)),
|
|
"this is some data",
|
|
base::unexpected(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE))));
|
|
|
|
} // namespace webui
|
|
|
|
} // namespace content
|