// Copyright (c) 2022 The Chromium Embedded Framework 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 "tests/ceftests/message_router_unittest_utils.h"
namespace {
const char kSingleQueryRequest[] = "request_context";
const char kSingleQueryResponse[] = "success_response";
const int kSingleQueryErrorCode = 5;
const char kSingleQueryErrorMessage[] = "error_message";
// Test a single query in a single page load.
class SingleQueryTestHandler : public SingleLoadTestHandler {
public:
enum TestType {
SUCCESS,
FAILURE,
CANCEL,
};
SingleQueryTestHandler(TestType type, bool sync_callback)
: test_type_(type), sync_callback_(sync_callback), query_id_(0) {}
std::string GetMainHTML() override {
std::string html;
std::stringstream ss;
ss << kSingleQueryErrorCode;
const std::string& errorCodeStr = ss.str();
html =
"
";
return html;
}
void OnNotify(CefRefPtr browser,
CefRefPtr frame,
const std::string& message) override {
AssertMainBrowser(browser);
AssertMainFrame(frame);
// OnNotify only be called once.
EXPECT_FALSE(got_notify_);
got_notify_.yes();
if (test_type_ == SUCCESS) {
EXPECT_STREQ("success", message.c_str());
} else if (test_type_ == FAILURE) {
EXPECT_STREQ("failure", message.c_str());
} else if (test_type_ == CANCEL) {
EXPECT_STREQ("cancel", message.c_str());
}
DestroyTestIfDone();
}
void ExecuteCallback() {
EXPECT_TRUE(callback_.get());
if (test_type_ == SUCCESS) {
callback_->Success(kSingleQueryResponse);
} else if (test_type_ == FAILURE) {
callback_->Failure(kSingleQueryErrorCode, kSingleQueryErrorMessage);
} else {
ADD_FAILURE(); // Not reached.
}
callback_ = nullptr;
}
bool OnQuery(CefRefPtr browser,
CefRefPtr frame,
int64_t query_id,
const CefString& request,
bool persistent,
CefRefPtr callback) override {
AssertMainBrowser(browser);
AssertMainFrame(frame);
EXPECT_NE(0, query_id);
EXPECT_FALSE(persistent);
EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str());
got_on_query_.yes();
query_id_ = query_id;
callback_ = callback;
if (test_type_ == SUCCESS || test_type_ == FAILURE) {
if (sync_callback_) {
ExecuteCallback();
} else {
CefPostTask(
TID_UI,
base::BindOnce(&SingleQueryTestHandler::ExecuteCallback, this));
}
}
return true;
}
void OnQueryCanceled(CefRefPtr browser,
CefRefPtr frame,
int64_t query_id) override {
AssertMainBrowser(browser);
AssertMainFrame(frame);
EXPECT_EQ(test_type_, CANCEL);
EXPECT_EQ(query_id_, query_id);
EXPECT_TRUE(got_on_query_);
EXPECT_TRUE(callback_.get());
got_on_query_canceled_.yes();
callback_ = nullptr;
DestroyTestIfDone();
}
void DestroyTestIfDone() {
bool destroy_test = false;
if (test_type_ == CANCEL) {
destroy_test = got_notify_ && got_on_query_canceled_;
} else {
destroy_test = got_notify_;
}
if (destroy_test) {
DestroyTest();
}
}
void DestroyTest() override {
EXPECT_TRUE(got_notify_);
EXPECT_TRUE(got_on_query_);
EXPECT_FALSE(callback_.get());
if (test_type_ == CANCEL) {
EXPECT_TRUE(got_on_query_canceled_);
} else {
EXPECT_FALSE(got_on_query_canceled_);
}
TestHandler::DestroyTest();
}
private:
const TestType test_type_;
const bool sync_callback_;
int64_t query_id_;
CefRefPtr callback_;
TrackCallback got_on_query_;
TrackCallback got_on_query_canceled_;
TrackCallback got_notify_;
};
} // namespace
// Test that a single query with successful result delivered synchronously.
TEST(MessageRouterTest, SingleQuerySuccessSyncCallback) {
CefRefPtr handler =
new SingleQueryTestHandler(SingleQueryTestHandler::SUCCESS, true);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Test that a single query with successful result delivered asynchronously.
TEST(MessageRouterTest, SingleQuerySuccessAsyncCallback) {
CefRefPtr handler =
new SingleQueryTestHandler(SingleQueryTestHandler::SUCCESS, false);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Test that a single query with failure result delivered synchronously.
TEST(MessageRouterTest, SingleQueryFailureSyncCallback) {
CefRefPtr handler =
new SingleQueryTestHandler(SingleQueryTestHandler::FAILURE, true);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Test that a single query with failure result delivered asynchronously.
TEST(MessageRouterTest, SingleQueryFailureAsyncCallback) {
CefRefPtr handler =
new SingleQueryTestHandler(SingleQueryTestHandler::FAILURE, false);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Test that a single query with cancellation.
TEST(MessageRouterTest, SingleQueryCancel) {
CefRefPtr handler =
new SingleQueryTestHandler(SingleQueryTestHandler::CANCEL, true);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
namespace {
const int kSinglePersistentQueryResponseCount = 10;
// Test a single persistent query in a single page load.
class SinglePersistentQueryTestHandler : public SingleLoadTestHandler {
public:
enum TestType {
SUCCESS,
FAILURE,
};
SinglePersistentQueryTestHandler(TestType test_type, bool sync_callback)
: test_type_(test_type), sync_callback_(sync_callback), query_id_(0) {}
std::string GetMainHTML() override {
std::string html;
std::stringstream ss;
ss << kSinglePersistentQueryResponseCount;
const std::string& responseCountStr = ss.str();
ss.str("");
ss << kSingleQueryErrorCode;
const std::string& errorCodeStr = ss.str();
html =
"";
return html;
}
void OnNotify(CefRefPtr browser,
CefRefPtr frame,
const std::string& message) override {
AssertMainBrowser(browser);
AssertMainFrame(frame);
if (test_type_ == SUCCESS) {
EXPECT_STREQ("success", message.c_str());
} else if (test_type_ == FAILURE) {
EXPECT_STREQ("failure", message.c_str());
}
got_notify_.yes();
DestroyTestIfDone();
}
void ExecuteCallback() {
EXPECT_TRUE(callback_.get());
if (test_type_ == SUCCESS) {
callback_->Success(kSingleQueryResponse);
} else {
callback_->Failure(kSingleQueryErrorCode, kSingleQueryErrorMessage);
callback_ = nullptr;
}
}
bool OnQuery(CefRefPtr browser,
CefRefPtr frame,
int64_t query_id,
const CefString& request,
bool persistent,
CefRefPtr callback) override {
AssertMainBrowser(browser);
AssertMainFrame(frame);
EXPECT_NE(0, query_id);
EXPECT_TRUE(persistent);
EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str());
got_on_query_.yes();
query_id_ = query_id;
callback_ = callback;
int repeat =
(test_type_ == SUCCESS ? kSinglePersistentQueryResponseCount : 1);
for (int i = 0; i < repeat; ++i) {
if (sync_callback_) {
ExecuteCallback();
} else {
CefPostTask(
TID_UI,
base::BindOnce(&SinglePersistentQueryTestHandler::ExecuteCallback,
this));
}
}
return true;
}
void OnQueryCanceled(CefRefPtr browser,
CefRefPtr frame,
int64_t query_id) override {
AssertMainBrowser(browser);
AssertMainFrame(frame);
EXPECT_EQ(query_id_, query_id);
EXPECT_TRUE(got_on_query_);
EXPECT_TRUE(callback_.get());
got_on_query_canceled_.yes();
callback_ = nullptr;
DestroyTestIfDone();
}
void DestroyTestIfDone() {
bool destroy_test = false;
if (test_type_ == SUCCESS) {
if (got_on_query_ && got_on_query_canceled_ && got_notify_) {
destroy_test = true;
}
} else if (got_on_query_ && got_notify_) {
destroy_test = true;
}
if (destroy_test) {
DestroyTest();
}
}
void DestroyTest() override {
EXPECT_TRUE(got_notify_);
EXPECT_TRUE(got_on_query_);
EXPECT_FALSE(callback_.get());
if (test_type_ == SUCCESS) {
EXPECT_TRUE(got_on_query_canceled_);
} else {
EXPECT_FALSE(got_on_query_canceled_);
}
TestHandler::DestroyTest();
}
private:
const TestType test_type_;
const bool sync_callback_;
int64_t query_id_;
CefRefPtr callback_;
TrackCallback got_on_query_;
TrackCallback got_on_query_canceled_;
TrackCallback got_notify_;
};
} // namespace
// Test that a single query with successful result delivered synchronously.
TEST(MessageRouterTest, SinglePersistentQuerySuccessSyncCallback) {
CefRefPtr handler =
new SinglePersistentQueryTestHandler(
SinglePersistentQueryTestHandler::SUCCESS, true);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Test that a single query with successful result delivered asynchronously.
TEST(MessageRouterTest, SinglePersistentQuerySuccessAsyncCallback) {
CefRefPtr handler =
new SinglePersistentQueryTestHandler(
SinglePersistentQueryTestHandler::SUCCESS, false);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Test that a single query with failure result delivered synchronously.
TEST(MessageRouterTest, SinglePersistentQueryFailureSyncCallback) {
CefRefPtr handler =
new SinglePersistentQueryTestHandler(
SinglePersistentQueryTestHandler::FAILURE, true);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Test that a single query with failure result delivered asynchronously.
TEST(MessageRouterTest, SinglePersistentQueryFailureAsyncCallback) {
CefRefPtr handler =
new SinglePersistentQueryTestHandler(
SinglePersistentQueryTestHandler::FAILURE, false);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
namespace {
// Test a single unhandled query in a single page load.
class SingleUnhandledQueryTestHandler : public SingleLoadTestHandler {
public:
SingleUnhandledQueryTestHandler() {}
std::string GetMainHTML() override {
std::string html;
html =
"";
return html;
}
void OnNotify(CefRefPtr browser,
CefRefPtr frame,
const std::string& message) override {
AssertMainBrowser(browser);
AssertMainFrame(frame);
EXPECT_STREQ("failure", message.c_str());
got_notify_.yes();
DestroyTest();
}
bool OnQuery(CefRefPtr browser,
CefRefPtr frame,
int64_t query_id,
const CefString& request,
bool persistent,
CefRefPtr callback) override {
AssertMainBrowser(browser);
AssertMainFrame(frame);
EXPECT_NE(0, query_id);
EXPECT_FALSE(persistent);
EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str());
got_on_query_.yes();
return false;
}
void OnQueryCanceled(CefRefPtr browser,
CefRefPtr frame,
int64_t query_id) override {
EXPECT_FALSE(true); // Not reached.
}
void DestroyTest() override {
EXPECT_TRUE(got_on_query_);
EXPECT_TRUE(got_notify_);
TestHandler::DestroyTest();
}
private:
TrackCallback got_on_query_;
TrackCallback got_notify_;
};
} // namespace
// Test that a single unhandled query results in a call to onFailure.
TEST(MessageRouterTest, SingleUnhandledQuery) {
CefRefPtr handler =
new SingleUnhandledQueryTestHandler();
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}