#include <atomic>
#include <memory>
#include <tuple>
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/notreached.h"
#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/task_environment.h"
#include "components/cronet/native/test/test_request_finished_info_listener.h"
#include "components/cronet/native/test/test_upload_data_provider.h"
#include "components/cronet/native/test/test_url_request_callback.h"
#include "components/cronet/native/test/test_util.h"
#include "cronet_c.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using cronet::test::TestRequestFinishedInfoListener;
using cronet::test::TestUploadDataProvider;
using cronet::test::TestUrlRequestCallback;
using ::testing::HasSubstr;
namespace {
class StatusListener {
public:
explicit StatusListener(TestUrlRequestCallback* callback)
: status_listener_(Cronet_UrlRequestStatusListener_CreateWith(
StatusListener::OnStatus)),
callback_(callback),
expect_request_not_done_(false) {
Cronet_UrlRequestStatusListener_SetClientContext(status_listener_, this);
}
StatusListener(const StatusListener&) = delete;
StatusListener& operator=(const StatusListener&) = delete;
~StatusListener() {
Cronet_UrlRequestStatusListener_Destroy(status_listener_);
}
Cronet_UrlRequestStatusListener_Status GetStatus(
Cronet_UrlRequestPtr request) {
Cronet_UrlRequest_GetStatus(request, status_listener_);
expect_request_not_done_ = !Cronet_UrlRequest_IsDone(request);
awaiting_status_.Wait();
return status_;
}
private:
static void OnStatus(Cronet_UrlRequestStatusListenerPtr self,
Cronet_UrlRequestStatusListener_Status status) {
StatusListener* listener = static_cast<StatusListener*>(
Cronet_UrlRequestStatusListener_GetClientContext(self));
if (listener->expect_request_not_done_)
EXPECT_FALSE(listener->callback_->IsDone());
listener->status_ = status;
listener->awaiting_status_.Signal();
}
Cronet_UrlRequestStatusListenerPtr const status_listener_;
const raw_ptr<TestUrlRequestCallback> callback_;
Cronet_UrlRequestStatusListener_Status status_ =
Cronet_UrlRequestStatusListener_Status_INVALID;
base::WaitableEvent awaiting_status_;
std::atomic_bool expect_request_not_done_;
};
enum class RequestFinishedListenerType {
kNoListener,
kUrlRequestListener,
kEngineListener,
};
int64_t DateToMillis(Cronet_DateTimePtr date_time) {
if (date_time == nullptr) {
return -1;
}
int64_t value = Cronet_DateTime_value_get(date_time);
EXPECT_NE(-1, value);
return value;
}
constexpr int64_t kDateOverrunThreshold = 1LL << 50;
void VerifyRequestMetrics(Cronet_MetricsPtr metrics) {
EXPECT_GE(DateToMillis(Cronet_Metrics_request_start_get(metrics)), 0);
EXPECT_LT(DateToMillis(Cronet_Metrics_request_start_get(metrics)),
kDateOverrunThreshold);
EXPECT_GE(DateToMillis(Cronet_Metrics_request_end_get(metrics)),
DateToMillis(Cronet_Metrics_request_start_get(metrics)));
EXPECT_LT(DateToMillis(Cronet_Metrics_request_end_get(metrics)),
kDateOverrunThreshold);
EXPECT_GE(DateToMillis(Cronet_Metrics_dns_start_get(metrics)), -1);
EXPECT_LT(DateToMillis(Cronet_Metrics_dns_start_get(metrics)),
kDateOverrunThreshold);
EXPECT_GE(DateToMillis(Cronet_Metrics_dns_end_get(metrics)),
DateToMillis(Cronet_Metrics_dns_start_get(metrics)));
EXPECT_LT(DateToMillis(Cronet_Metrics_dns_end_get(metrics)),
kDateOverrunThreshold);
EXPECT_GE(DateToMillis(Cronet_Metrics_connect_start_get(metrics)), -1);
EXPECT_LT(DateToMillis(Cronet_Metrics_connect_start_get(metrics)),
kDateOverrunThreshold);
EXPECT_GE(DateToMillis(Cronet_Metrics_connect_end_get(metrics)),
DateToMillis(Cronet_Metrics_connect_start_get(metrics)));
EXPECT_LT(DateToMillis(Cronet_Metrics_connect_end_get(metrics)),
kDateOverrunThreshold);
EXPECT_GE(DateToMillis(Cronet_Metrics_ssl_start_get(metrics)), -1);
EXPECT_LT(DateToMillis(Cronet_Metrics_ssl_start_get(metrics)),
kDateOverrunThreshold);
EXPECT_GE(DateToMillis(Cronet_Metrics_ssl_end_get(metrics)),
DateToMillis(Cronet_Metrics_ssl_start_get(metrics)));
EXPECT_LT(DateToMillis(Cronet_Metrics_ssl_end_get(metrics)),
kDateOverrunThreshold);
EXPECT_GE(DateToMillis(Cronet_Metrics_sending_start_get(metrics)), -1);
EXPECT_LT(DateToMillis(Cronet_Metrics_sending_start_get(metrics)),
kDateOverrunThreshold);
EXPECT_GE(DateToMillis(Cronet_Metrics_sending_end_get(metrics)),
DateToMillis(Cronet_Metrics_sending_start_get(metrics)));
EXPECT_LT(DateToMillis(Cronet_Metrics_sending_end_get(metrics)),
kDateOverrunThreshold);
EXPECT_GE(DateToMillis(Cronet_Metrics_push_start_get(metrics)), -1);
EXPECT_LT(DateToMillis(Cronet_Metrics_push_start_get(metrics)),
kDateOverrunThreshold);
EXPECT_GE(DateToMillis(Cronet_Metrics_push_end_get(metrics)),
DateToMillis(Cronet_Metrics_push_start_get(metrics)));
EXPECT_LT(DateToMillis(Cronet_Metrics_push_end_get(metrics)),
kDateOverrunThreshold);
EXPECT_GE(DateToMillis(Cronet_Metrics_response_start_get(metrics)), -1);
EXPECT_LT(DateToMillis(Cronet_Metrics_response_start_get(metrics)),
kDateOverrunThreshold);
EXPECT_GE(Cronet_Metrics_sent_byte_count_get(metrics), -1);
EXPECT_GE(Cronet_Metrics_received_byte_count_get(metrics), -1);
if (Cronet_Metrics_dns_start_get(metrics) != nullptr) {
EXPECT_GE(DateToMillis(Cronet_Metrics_dns_start_get(metrics)),
DateToMillis(Cronet_Metrics_request_start_get(metrics)));
}
if (Cronet_Metrics_connect_start_get(metrics) != nullptr &&
Cronet_Metrics_dns_end_get(metrics) != nullptr) {
EXPECT_GE(DateToMillis(Cronet_Metrics_connect_start_get(metrics)),
DateToMillis(Cronet_Metrics_dns_end_get(metrics)));
}
if (Cronet_Metrics_ssl_start_get(metrics) != nullptr &&
Cronet_Metrics_connect_start_get(metrics) != nullptr) {
EXPECT_GE(DateToMillis(Cronet_Metrics_ssl_start_get(metrics)),
DateToMillis(Cronet_Metrics_connect_start_get(metrics)));
}
if (Cronet_Metrics_connect_end_get(metrics) != nullptr &&
Cronet_Metrics_ssl_end_get(metrics) != nullptr) {
EXPECT_GE(DateToMillis(Cronet_Metrics_connect_end_get(metrics)),
DateToMillis(Cronet_Metrics_ssl_end_get(metrics)));
}
if (Cronet_Metrics_sending_start_get(metrics) != nullptr &&
Cronet_Metrics_connect_end_get(metrics) != nullptr) {
EXPECT_GE(DateToMillis(Cronet_Metrics_sending_start_get(metrics)),
DateToMillis(Cronet_Metrics_connect_end_get(metrics)));
}
if (Cronet_Metrics_response_start_get(metrics) != nullptr &&
Cronet_Metrics_sending_end_get(metrics) != nullptr) {
EXPECT_GE(DateToMillis(Cronet_Metrics_response_start_get(metrics)),
DateToMillis(Cronet_Metrics_sending_end_get(metrics)));
}
if (Cronet_Metrics_response_start_get(metrics) != nullptr) {
EXPECT_GE(DateToMillis(Cronet_Metrics_request_end_get(metrics)),
DateToMillis(Cronet_Metrics_response_start_get(metrics)));
}
}
Cronet_RequestFinishedInfo_FINISHED_REASON MapFinishedReason(
TestUrlRequestCallback::ResponseStep response_step) {
switch (response_step) {
case TestUrlRequestCallback::ON_SUCCEEDED:
return Cronet_RequestFinishedInfo_FINISHED_REASON_SUCCEEDED;
case TestUrlRequestCallback::ON_FAILED:
return Cronet_RequestFinishedInfo_FINISHED_REASON_FAILED;
case TestUrlRequestCallback::ON_CANCELED:
return Cronet_RequestFinishedInfo_FINISHED_REASON_CANCELED;
default:
NOTREACHED() << "Unknown TestUrlRequestCallback::ResponseStep: "
<< response_step;
}
}
void VerifyRequestFinishedInfoListener(
TestRequestFinishedInfoListener* test_request_finished_info_listener,
const TestUrlRequestCallback& callback) {
Cronet_RequestFinishedInfoPtr request_info =
test_request_finished_info_listener->request_finished_info();
VerifyRequestMetrics(Cronet_RequestFinishedInfo_metrics_get(request_info));
auto finished_reason =
Cronet_RequestFinishedInfo_finished_reason_get(request_info);
EXPECT_EQ(MapFinishedReason(callback.response_step()), finished_reason);
EXPECT_EQ(callback.original_response_info(),
test_request_finished_info_listener->url_response_info());
EXPECT_EQ(callback.last_error(),
test_request_finished_info_listener->error());
}
class UrlRequestTest : public ::testing::TestWithParam<
std::tuple<bool, RequestFinishedListenerType>> {
public:
UrlRequestTest(const UrlRequestTest&) = delete;
UrlRequestTest& operator=(const UrlRequestTest&) = delete;
protected:
UrlRequestTest() = default;
~UrlRequestTest() override = default;
void SetUp() override {}
void TearDown() override {}
bool GetDirectExecutorParam() { return std::get<0>(GetParam()); }
RequestFinishedListenerType GetRequestFinishedListenerTypeParam() {
return std::get<1>(GetParam());
}
std::unique_ptr<TestUrlRequestCallback> StartAndWaitForComplete(
const std::string& url,
std::unique_ptr<TestUrlRequestCallback> test_callback,
const std::string& http_method,
TestUploadDataProvider* test_upload_data_provider,
int remapped_port) {
Cronet_EnginePtr engine = cronet::test::CreateTestEngine(remapped_port);
Cronet_UrlRequestPtr request = Cronet_UrlRequest_Create();
Cronet_UrlRequestParamsPtr request_params =
Cronet_UrlRequestParams_Create();
Cronet_UrlRequestParams_http_method_set(request_params,
http_method.c_str());
Cronet_UploadDataProviderPtr upload_data_provider = nullptr;
if (test_upload_data_provider != nullptr) {
test_upload_data_provider->set_url_request(request);
upload_data_provider =
test_upload_data_provider->CreateUploadDataProvider();
Cronet_UrlRequestParams_upload_data_provider_set(request_params,
upload_data_provider);
Cronet_UrlRequestParams_upload_data_provider_executor_set(
request_params, test_upload_data_provider->executor());
Cronet_HttpHeaderPtr header = Cronet_HttpHeader_Create();
Cronet_HttpHeader_name_set(header, "Content-Type");
Cronet_HttpHeader_value_set(header, "Useless/string");
Cronet_UrlRequestParams_request_headers_add(request_params, header);
Cronet_HttpHeader_Destroy(header);
}
Cronet_ExecutorPtr executor = test_callback->GetExecutor();
Cronet_UrlRequestCallbackPtr callback =
test_callback->CreateUrlRequestCallback();
TestRequestFinishedInfoListener test_request_finished_info_listener;
MaybeAddRequestFinishedListener(request_params, engine, executor,
&test_request_finished_info_listener);
Cronet_UrlRequest_InitWithParams(request, engine, url.c_str(),
request_params, callback, executor);
Cronet_UrlRequest_Start(request);
test_callback->WaitForDone();
MaybeVerifyRequestFinishedInfo(&test_request_finished_info_listener,
*test_callback);
CleanupRequestFinishedListener(request_params, engine);
test_callback->ShutdownExecutor();
EXPECT_TRUE(test_callback->IsDone());
EXPECT_TRUE(Cronet_UrlRequest_IsDone(request));
if (upload_data_provider != nullptr)
Cronet_UploadDataProvider_Destroy(upload_data_provider);
Cronet_UrlRequestParams_Destroy(request_params);
Cronet_UrlRequest_Destroy(request);
Cronet_UrlRequestCallback_Destroy(callback);
Cronet_Engine_Destroy(engine);
return test_callback;
}
std::unique_ptr<TestUrlRequestCallback> StartAndWaitForComplete(
const std::string& url,
std::unique_ptr<TestUrlRequestCallback> test_callback,
const std::string& http_method,
TestUploadDataProvider* test_upload_data_provider) {
return StartAndWaitForComplete(url, std::move(test_callback), http_method,
test_upload_data_provider,
0);
}
std::unique_ptr<TestUrlRequestCallback> StartAndWaitForComplete(
const std::string& url,
std::unique_ptr<TestUrlRequestCallback> test_callback) {
return StartAndWaitForComplete(url, std::move(test_callback),
std::string(),
nullptr);
}
std::unique_ptr<TestUrlRequestCallback> StartAndWaitForComplete(
const std::string& url) {
return StartAndWaitForComplete(
url,
std::make_unique<TestUrlRequestCallback>(GetDirectExecutorParam()));
}
void CheckResponseInfo(
const TestUrlRequestCallback::UrlResponseInfo& response_info,
const std::string& expected_url,
int expected_http_status_code,
const std::string& expected_http_status_text) {
EXPECT_EQ(expected_url, response_info.url);
EXPECT_EQ(expected_url, response_info.url_chain.back());
EXPECT_EQ(expected_http_status_code, response_info.http_status_code);
EXPECT_EQ(expected_http_status_text, response_info.http_status_text);
EXPECT_FALSE(response_info.was_cached);
}
void ExpectResponseInfoEquals(
const TestUrlRequestCallback::UrlResponseInfo& expected,
const TestUrlRequestCallback::UrlResponseInfo& actual) {
EXPECT_EQ(expected.url, actual.url);
EXPECT_EQ(expected.url_chain, actual.url_chain);
EXPECT_EQ(expected.http_status_code, actual.http_status_code);
EXPECT_EQ(expected.http_status_text, actual.http_status_text);
EXPECT_EQ(expected.all_headers, actual.all_headers);
EXPECT_EQ(expected.was_cached, actual.was_cached);
EXPECT_EQ(expected.negotiated_protocol, actual.negotiated_protocol);
EXPECT_EQ(expected.proxy_server, actual.proxy_server);
EXPECT_EQ(expected.received_byte_count, actual.received_byte_count);
}
void MaybeAddRequestFinishedListener(
Cronet_UrlRequestParamsPtr url_request_params,
Cronet_EnginePtr engine,
Cronet_ExecutorPtr executor,
TestRequestFinishedInfoListener* test_request_finished_info_listener) {
auto request_finished_listener_type = GetRequestFinishedListenerTypeParam();
if (request_finished_listener_type ==
RequestFinishedListenerType::kNoListener)
return;
request_finished_listener_ =
test_request_finished_info_listener->CreateRequestFinishedListener();
switch (request_finished_listener_type) {
case RequestFinishedListenerType::kUrlRequestListener:
Cronet_UrlRequestParams_request_finished_listener_set(
url_request_params, request_finished_listener_);
Cronet_UrlRequestParams_request_finished_executor_set(
url_request_params, executor);
break;
case RequestFinishedListenerType::kEngineListener:
Cronet_Engine_AddRequestFinishedListener(
engine, request_finished_listener_, executor);
break;
default:
NOTREACHED();
}
}
void CleanupRequestFinishedListener(
Cronet_UrlRequestParamsPtr url_request_params,
Cronet_EnginePtr engine) {
auto request_finished_listener_type = GetRequestFinishedListenerTypeParam();
if (request_finished_listener_type ==
RequestFinishedListenerType::kEngineListener) {
Cronet_Engine_RemoveRequestFinishedListener(engine,
request_finished_listener_);
}
Cronet_UrlRequestParams_request_finished_listener_set(url_request_params,
nullptr);
Cronet_UrlRequestParams_request_finished_executor_set(url_request_params,
nullptr);
}
void MaybeVerifyRequestFinishedInfo(
TestRequestFinishedInfoListener* test_request_finished_info_listener,
const TestUrlRequestCallback& callback) {
if (GetRequestFinishedListenerTypeParam() ==
RequestFinishedListenerType::kNoListener)
return;
test_request_finished_info_listener->WaitForDone();
VerifyRequestFinishedInfoListener(test_request_finished_info_listener,
callback);
}
void TestCancel(TestUrlRequestCallback::FailureType failure_type,
TestUrlRequestCallback::ResponseStep failure_step,
bool expect_response_info,
bool expect_error);
protected:
base::test::SingleThreadTaskEnvironment task_environment_;
Cronet_RequestFinishedInfoListenerPtr request_finished_listener_ = nullptr;
};
const bool kDirectExecutorEnabled[]{true, false};
INSTANTIATE_TEST_SUITE_P(
NoRequestFinishedListener,
UrlRequestTest,
testing::Combine(
testing::ValuesIn(kDirectExecutorEnabled),
testing::Values(RequestFinishedListenerType::kNoListener)));
INSTANTIATE_TEST_SUITE_P(
RequestFinishedListenerOnUrlRequest,
UrlRequestTest,
testing::Combine(
testing::ValuesIn(kDirectExecutorEnabled),
testing::Values(RequestFinishedListenerType::kUrlRequestListener)));
INSTANTIATE_TEST_SUITE_P(
RequestFinishedListenerOnEngine,
UrlRequestTest,
testing::Combine(
testing::ValuesIn(kDirectExecutorEnabled),
testing::Values(RequestFinishedListenerType::kEngineListener)));
TEST_P(UrlRequestTest, SSLCertificateError) {
net::EmbeddedTestServer ssl_server(net::EmbeddedTestServer::TYPE_HTTPS);
ssl_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
ASSERT_TRUE(ssl_server.Start());
const std::string url = ssl_server.GetURL("/").spec();
TestUploadDataProvider data_provider(TestUploadDataProvider::SYNC,
nullptr);
data_provider.AddRead("Test");
auto callback =
std::make_unique<TestUrlRequestCallback>(GetDirectExecutorParam());
callback = StartAndWaitForComplete(url, std::move(callback), std::string(),
&data_provider);
data_provider.AssertClosed();
EXPECT_EQ(4, data_provider.GetUploadedLength());
EXPECT_EQ(0, data_provider.num_read_calls());
EXPECT_EQ(0, data_provider.num_rewind_calls());
EXPECT_EQ(nullptr, callback->response_info());
EXPECT_EQ("", callback->response_as_string());
EXPECT_EQ("net::ERR_CERT_INVALID", callback->last_error_message());
}
TEST_P(UrlRequestTest, SSLUpload) {
net::EmbeddedTestServer ssl_server(net::EmbeddedTestServer::TYPE_HTTPS);
net::test_server::RegisterDefaultHandlers(&ssl_server);
ASSERT_TRUE(ssl_server.Start());
constexpr char kUrl[] = "https://test.example.com/echoall";
constexpr char kUploadString[] =
"The quick brown fox jumps over the lazy dog.";
TestUploadDataProvider data_provider(TestUploadDataProvider::SYNC,
nullptr);
data_provider.AddRead(kUploadString);
auto callback =
std::make_unique<TestUrlRequestCallback>(GetDirectExecutorParam());
callback = StartAndWaitForComplete(kUrl, std::move(callback), std::string(),
&data_provider, ssl_server.port());
data_provider.AssertClosed();
EXPECT_NE(nullptr, callback->response_info());
EXPECT_EQ("", callback->last_error_message());
EXPECT_EQ(200, callback->response_info()->http_status_code);
EXPECT_THAT(callback->response_as_string(), HasSubstr(kUploadString));
}
TEST_P(UrlRequestTest, UploadFailsWithoutInitializingStream) {
const std::string url = "http://127.0.0.1:319";
TestUploadDataProvider data_provider(TestUploadDataProvider::SYNC,
nullptr);
data_provider.AddRead("Test");
auto callback =
std::make_unique<TestUrlRequestCallback>(GetDirectExecutorParam());
callback = StartAndWaitForComplete(url, std::move(callback), std::string(),
&data_provider);
data_provider.AssertClosed();
EXPECT_EQ(0, data_provider.num_read_calls());
EXPECT_EQ(0, data_provider.num_rewind_calls());
EXPECT_EQ(nullptr, callback->response_info());
EXPECT_EQ("", callback->response_as_string());
EXPECT_TRUE(callback->on_error_called());
}
TEST_P(UrlRequestTest, FailedRequestHostNotFound) {
Cronet_EnginePtr engine = cronet::test::CreateTestEngine(0);
Cronet_UrlRequestPtr request = Cronet_UrlRequest_Create();
Cronet_UrlRequestParamsPtr request_params = Cronet_UrlRequestParams_Create();
std::string url = "https://notfound.example.com";
TestUrlRequestCallback test_callback(GetDirectExecutorParam());
Cronet_ExecutorPtr executor = test_callback.GetExecutor();
Cronet_UrlRequestCallbackPtr callback =
test_callback.CreateUrlRequestCallback();
TestRequestFinishedInfoListener test_request_finished_info_listener;
MaybeAddRequestFinishedListener(request_params, engine, executor,
&test_request_finished_info_listener);
Cronet_UrlRequest_InitWithParams(request, engine, url.c_str(), request_params,
callback, executor);
Cronet_UrlRequest_Start(request);
test_callback.WaitForDone();
MaybeVerifyRequestFinishedInfo(&test_request_finished_info_listener,
test_callback);
EXPECT_TRUE(test_callback.IsDone());
EXPECT_TRUE(test_callback.on_error_called());
EXPECT_FALSE(test_callback.on_canceled_called());
EXPECT_TRUE(test_callback.response_as_string().empty());
EXPECT_EQ(nullptr, test_callback.response_info());
EXPECT_NE(nullptr, test_callback.last_error());
EXPECT_EQ(Cronet_Error_ERROR_CODE_ERROR_HOSTNAME_NOT_RESOLVED,
Cronet_Error_error_code_get(test_callback.last_error()));
EXPECT_FALSE(
Cronet_Error_immediately_retryable_get(test_callback.last_error()));
EXPECT_STREQ("net::ERR_NAME_NOT_RESOLVED",
Cronet_Error_message_get(test_callback.last_error()));
EXPECT_EQ(-105,
Cronet_Error_internal_error_code_get(test_callback.last_error()));
EXPECT_EQ(
0, Cronet_Error_quic_detailed_error_code_get(test_callback.last_error()));
Cronet_UrlRequestParams_Destroy(request_params);
Cronet_UrlRequest_Destroy(request);
Cronet_UrlRequestCallback_Destroy(callback);
Cronet_Engine_Destroy(engine);
}
class UrlRequestTestNoParam : public ::testing::Test {
void SetUp() override {}
void TearDown() override {}
};
TEST_F(UrlRequestTestNoParam,
RequestFinishedListenerWithoutExecutorReturnsError) {
Cronet_EngineParamsPtr engine_params = Cronet_EngineParams_Create();
Cronet_EnginePtr engine = Cronet_Engine_Create();
Cronet_EngineParams_enable_check_result_set(engine_params, false);
EXPECT_EQ(Cronet_RESULT_SUCCESS,
Cronet_Engine_StartWithParams(engine, engine_params));
Cronet_EngineParams_Destroy(engine_params);
Cronet_UrlRequestPtr request = Cronet_UrlRequest_Create();
Cronet_UrlRequestParamsPtr request_params = Cronet_UrlRequestParams_Create();
TestRequestFinishedInfoListener test_request_finished_info_listener;
Cronet_RequestFinishedInfoListenerPtr request_finished_listener =
test_request_finished_info_listener.CreateRequestFinishedListener();
TestUrlRequestCallback test_callback(true);
Cronet_ExecutorPtr executor = test_callback.GetExecutor();
Cronet_UrlRequestCallbackPtr callback =
test_callback.CreateUrlRequestCallback();
Cronet_UrlRequestParams_request_finished_listener_set(
request_params, request_finished_listener);
EXPECT_EQ(Cronet_RESULT_NULL_POINTER_REQUEST_FINISHED_INFO_LISTENER_EXECUTOR,
Cronet_UrlRequest_InitWithParams(
request, engine, "http://fakeurl.example.com", request_params,
callback, executor));
Cronet_RequestFinishedInfoListener_Destroy(request_finished_listener);
Cronet_UrlRequestParams_Destroy(request_params);
Cronet_UrlRequest_Destroy(request);
Cronet_UrlRequestCallback_Destroy(callback);
Cronet_Engine_Destroy(engine);
}
TEST_F(UrlRequestTestNoParam,
UseRequestFinishedInfoAfterUrlRequestDestructionFailure) {
Cronet_EnginePtr engine = cronet::test::CreateTestEngine(0);
Cronet_UrlRequestPtr request = Cronet_UrlRequest_Create();
Cronet_UrlRequestParamsPtr request_params = Cronet_UrlRequestParams_Create();
std::string url = "https://notfound.example.com";
TestUrlRequestCallback test_callback( false);
Cronet_ExecutorPtr executor = test_callback.GetExecutor();
Cronet_UrlRequestCallbackPtr callback =
test_callback.CreateUrlRequestCallback();
base::WaitableEvent done_event;
struct ListenerContext {
raw_ptr<TestUrlRequestCallback> test_callback;
Cronet_UrlRequestPtr url_request;
raw_ptr<base::WaitableEvent> done_event;
};
ListenerContext listener_context = {&test_callback, request, &done_event};
auto* request_finished_listener =
Cronet_RequestFinishedInfoListener_CreateWith(
+[](Cronet_RequestFinishedInfoListenerPtr self,
Cronet_RequestFinishedInfoPtr request_finished_info,
Cronet_UrlResponseInfoPtr response_info, Cronet_ErrorPtr error) {
auto* listener_context = static_cast<ListenerContext*>(
Cronet_RequestFinishedInfoListener_GetClientContext(self));
listener_context->test_callback->WaitForDone();
Cronet_UrlRequest_Destroy(listener_context->url_request);
EXPECT_NE(nullptr, Cronet_RequestFinishedInfo_metrics_get(
request_finished_info));
EXPECT_NE(nullptr, Cronet_Error_message_get(error));
Cronet_RequestFinishedInfoListener_Destroy(self);
listener_context->done_event->Signal();
});
Cronet_RequestFinishedInfoListener_SetClientContext(request_finished_listener,
&listener_context);
Cronet_UrlRequestParams_request_finished_listener_set(
request_params, request_finished_listener);
Cronet_UrlRequestParams_request_finished_executor_set(request_params,
executor);
Cronet_UrlRequest_InitWithParams(request, engine, url.c_str(), request_params,
callback, executor);
Cronet_UrlRequest_Start(request);
done_event.Wait();
EXPECT_TRUE(test_callback.IsDone());
Cronet_UrlRequestParams_Destroy(request_params);
Cronet_UrlRequestCallback_Destroy(callback);
Cronet_Engine_Destroy(engine);
}
}