diff options
Diffstat (limited to 'tests/ceftests/test_server_observer_unittest.cc')
-rw-r--r-- | tests/ceftests/test_server_observer_unittest.cc | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/tests/ceftests/test_server_observer_unittest.cc b/tests/ceftests/test_server_observer_unittest.cc new file mode 100644 index 00000000..dca95560 --- /dev/null +++ b/tests/ceftests/test_server_observer_unittest.cc @@ -0,0 +1,232 @@ +// Copyright (c) 2020 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 <sstream> + +#include "include/cef_command_line.h" +#include "include/cef_task.h" +#include "include/cef_waitable_event.h" +#include "include/wrapper/cef_closure_task.h" +#include "include/wrapper/cef_helpers.h" +#include "tests/ceftests/test_request.h" +#include "tests/ceftests/test_server_observer.h" +#include "tests/ceftests/test_util.h" +#include "tests/ceftests/track_callback.h" +#include "tests/gtest/include/gtest/gtest.h" + +namespace { + +struct TestState { + bool https_server = false; + + TrackCallback got_initialized_; + TrackCallback got_request_; + TrackCallback got_response_; + TrackCallback got_shutdown_; + + bool ExpectAll() { + EXPECT_TRUE(got_initialized_); + EXPECT_TRUE(got_request_); + EXPECT_TRUE(got_response_); + EXPECT_TRUE(got_shutdown_); + return got_initialized_ && got_request_ && got_response_ && got_shutdown_; + } +}; + +const char kResponseData[] = "Test data"; + +class TestServerObserver : public test_server::ObserverHelper { + public: + TestServerObserver(TestState* state, + const std::string& path, + base::OnceClosure done_callback) + : state_(state), + path_(path), + done_callback_(std::move(done_callback)), + weak_ptr_factory_(this) { + DCHECK(state); + DCHECK(!path.empty()); + DCHECK(!done_callback_.is_null()); + Initialize(state_->https_server); + } + + ~TestServerObserver() override { std::move(done_callback_).Run(); } + + void OnInitialized(const std::string& server_origin) override { + CEF_REQUIRE_UI_THREAD(); + EXPECT_FALSE(state_->got_initialized_); + EXPECT_FALSE(state_->got_request_); + EXPECT_FALSE(state_->got_response_); + EXPECT_FALSE(state_->got_shutdown_); + + state_->got_initialized_.yes(); + + url_ = server_origin + path_; + + // Send a request to the server. + test_request::SendConfig config; + config.request_ = CefRequest::Create(); + config.request_->SetURL(url_); + test_request::Send(config, + base::BindOnce(&TestServerObserver::OnRequestResponse, + weak_ptr_factory_.GetWeakPtr())); + } + + bool OnTestServerRequest(CefRefPtr<CefRequest> request, + const ResponseCallback& response_callback) override { + CEF_REQUIRE_UI_THREAD(); + const std::string& url = request->GetURL(); + if (url != url_) { + return false; + } + + EXPECT_TRUE(state_->got_initialized_); + EXPECT_FALSE(state_->got_request_); + EXPECT_FALSE(state_->got_response_); + EXPECT_FALSE(state_->got_shutdown_); + + state_->got_request_.yes(); + + auto response = CefResponse::Create(); + response->SetStatus(200); + response->SetMimeType("text/plain"); + + response_callback.Run(response, kResponseData); + + // Stop propagating the callback. + return true; + } + + void OnRequestResponse(const test_request::State& state) { + CEF_REQUIRE_UI_THREAD(); + // Don't test for disconnected, which may race response. + EXPECT_TRUE(state_->got_initialized_); + EXPECT_TRUE(state_->got_request_); + EXPECT_FALSE(state_->got_response_); + EXPECT_FALSE(state_->got_shutdown_); + + state_->got_response_.yes(); + + EXPECT_STREQ(url_.c_str(), state.request_->GetURL().ToString().c_str()); + EXPECT_EQ(UR_SUCCESS, state.status_); + EXPECT_EQ(ERR_NONE, state.error_code_); + EXPECT_EQ(200, state.response_->GetStatus()); + EXPECT_STREQ(kResponseData, state.download_data_.c_str()); + + // Trigger shutdown asynchronously. + CefPostTask(TID_UI, base::BindOnce(&TestServerObserver::Shutdown, + weak_ptr_factory_.GetWeakPtr())); + } + + void OnShutdown() override { + CEF_REQUIRE_UI_THREAD(); + EXPECT_TRUE(state_->got_initialized_); + EXPECT_TRUE(state_->got_request_); + EXPECT_TRUE(state_->got_response_); + EXPECT_FALSE(state_->got_shutdown_); + + state_->got_shutdown_.yes(); + + // End the test. + delete this; + } + + private: + TestState* const state_; + const std::string path_; + base::OnceClosure done_callback_; + + std::string url_; + + base::WeakPtrFactory<TestServerObserver> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(TestServerObserver); +}; + +void CreateObserverOnUIThread(TestState* state, + const std::string& path, + base::OnceClosure done_callback) { + if (!CefCurrentlyOn(TID_UI)) { + CefPostTask(TID_UI, base::BindOnce(CreateObserverOnUIThread, + base::Unretained(state), path, + std::move(done_callback))); + return; + } + + new TestServerObserver(state, path, std::move(done_callback)); +} + +void SignalIfDone(CefRefPtr<CefWaitableEvent> event, + size_t* count, + size_t total) { + if (++(*count) == total) { + event->Signal(); + } +} + +void Wait(CefRefPtr<CefWaitableEvent> event) { + const auto timeout = GetConfiguredTestTimeout(/*timeout_ms=*/2000); + if (!timeout) { + event->Wait(); + } else { + event->TimedWait(*timeout); + } +} + +void RunHelperSingle(bool https_server) { + CefRefPtr<CefWaitableEvent> event = + CefWaitableEvent::CreateWaitableEvent(true, false); + + TestState state; + state.https_server = https_server; + CreateObserverOnUIThread(&state, "/TestServerTest.ObserverHelperSingle", + base::BindOnce(&CefWaitableEvent::Signal, event)); + + Wait(event); + + EXPECT_TRUE(state.ExpectAll()); +} + +void RunHelperMultiple(bool https_server) { + CefRefPtr<CefWaitableEvent> event = + CefWaitableEvent::CreateWaitableEvent(true, false); + + TestState states[3]; + size_t count = 0; + const size_t size = std::size(states); + + for (size_t i = 0; i < size; ++i) { + std::stringstream ss; + ss << "/TestServerTest.ObserverHelperMultiple" << i; + auto done_callback = + base::BindOnce(SignalIfDone, event, base::Unretained(&count), size); + states[i].https_server = https_server; + CreateObserverOnUIThread(&states[i], ss.str(), std::move(done_callback)); + } + + Wait(event); + + EXPECT_EQ(size, count); + for (size_t i = 0; i < size; ++i) { + EXPECT_TRUE(states[i].ExpectAll()) << i; + } +} + +} // namespace + +TEST(TestServerObserverTest, HelperSingleHttp) { + RunHelperSingle(/*https_server=*/false); +} + +TEST(TestServerObserverTest, HelperMultipleHttp) { + RunHelperMultiple(/*https_server=*/false); +} + +TEST(TestServerObserverTest, HelperSingleHttps) { + RunHelperSingle(/*https_server=*/true); +} + +TEST(TestServerObserverTest, HelperMultipleHttps) { + RunHelperMultiple(/*https_server=*/true); +} |