Remove Chromium target dependencies for unit tests (issue #1632)

This commit is contained in:
Marshall Greenblatt 2016-11-16 15:24:13 -05:00
parent ef6df50bf9
commit f557d325c1
18 changed files with 263 additions and 263 deletions

View File

@ -860,7 +860,7 @@ static_library("libcef_static") {
#
# Configuration that will be applied to all targets that depend on
# libcef_dll_wrapper or libcef_dll_wrapper_unittests.
# libcef_dll_wrapper.
config("libcef_dll_wrapper_config") {
include_dirs = [
".",
@ -873,60 +873,21 @@ config("libcef_dll_wrapper_config") {
defines = [ "USING_CEF_SHARED" ]
}
# Configuration that will be applied to all targets that depend on
# libcef_dll_wrapper_unittests.
config("libcef_dll_wrapper_unittests_config") {
defines = [ "USING_CHROMIUM_INCLUDES" ]
}
# libcef_dll_wrapper target.
static_library("libcef_dll_wrapper") {
sources = gypi_paths2.includes_common +
gypi_paths.autogen_cpp_includes +
gypi_paths2.includes_capi +
gypi_paths.autogen_capi_includes +
gypi_paths2.includes_wrapper +
gypi_paths2.libcef_dll_wrapper_sources_base +
gypi_paths2.libcef_dll_wrapper_sources_common +
gypi_paths.autogen_client_side
# Helper for creating normal and test versions of the libcef_dll_wrapper target.
template("libcef_dll_wrapper") {
static_library("${target_name}") {
testonly = defined(invoker.testonly) && invoker.testonly
sources = gypi_paths2.includes_common +
gypi_paths.autogen_cpp_includes +
gypi_paths2.includes_capi +
gypi_paths.autogen_capi_includes +
gypi_paths2.includes_wrapper +
gypi_paths2.libcef_dll_wrapper_sources_common +
gypi_paths.autogen_client_side
if (!testonly) {
sources += gypi_paths2.libcef_dll_wrapper_sources_base
}
if (defined(invoker.configs)) {
configs += invoker.configs
}
if (defined(invoker.public_configs)) {
public_configs = invoker.public_configs
}
}
}
# libcef_dll_wrapper target for normal executables.
libcef_dll_wrapper("libcef_dll_wrapper") {
configs = [ ":libcef_dll_wrapper_config" ]
configs += [ ":libcef_dll_wrapper_config" ]
public_configs = [ ":libcef_dll_wrapper_config" ]
}
# libcef_dll_wrapper target for test executables. Uses Chromium base/ includes
# instead of CEF base/ includes. A separate target is necessary to resolve
# cef_unittests linker errors as the Chromium base/ implementation diverges
# from the CEF implementation.
libcef_dll_wrapper("libcef_dll_wrapper_unittests") {
testonly = true
configs = [
":libcef_dll_wrapper_config",
":libcef_dll_wrapper_unittests_config",
]
public_configs = [
":libcef_dll_wrapper_config",
":libcef_dll_wrapper_unittests_config",
]
}
#
# cef_sandbox target.
@ -1443,14 +1404,7 @@ if (use_aura) {
# cef_unittests shared deps.
cef_unittests_deps = [
"//base",
"//base:i18n",
"//base/test:test_support",
"//build/config/sanitizers:deps",
"//testing/gtest",
"//third_party/icu",
"//third_party/zlib:zip",
"//ui/base",
]
if (is_mac) {
@ -1730,7 +1684,7 @@ if (is_mac) {
"tests/unittests/v8_unittest.cc",
]
helper_deps = cef_unittests_deps + [
":libcef_dll_wrapper_unittests",
":libcef_dll_wrapper",
]
info_plist = "tests/cefclient/resources/mac/Info.plist"
@ -1746,7 +1700,7 @@ if (is_mac) {
":cefclient_resources_bundle_data",
":cefclient_resources_bundle_data_english",
":cefclient_xibs",
":libcef_dll_wrapper_unittests",
":libcef_dll_wrapper",
]
libs = [
"AppKit.framework",
@ -1921,7 +1875,8 @@ if (is_mac) {
deps = cef_unittests_deps + [
":libcef",
":libcef_dll_wrapper_unittests",
":libcef_dll_wrapper",
"//build/config/sanitizers:deps",
]
if (is_win) {
@ -1950,6 +1905,10 @@ if (is_mac) {
"tests/cefclient/browser/resource_util_posix.cc",
]
libs = [
"X11",
]
deps += [
":copy_cefclient_files",
]

View File

@ -36,13 +36,6 @@
// When building CEF include the Chromium header directly.
#include "base/macros.h"
// Chromium uses movable types.
#define MOVE_SCOPED_PTR(var) std::move(var)
// Chromium uses std types.
#define SCOPED_PTR(type) std::unique_ptr<type>
#define DEFAULT_DELETER(type) std::default_delete<type>
#else // !USING_CHROMIUM_INCLUDES
// The following is substantially similar to the Chromium implementation.
// If the Chromium implementation diverges the below implementation should be
@ -51,13 +44,6 @@
#include <stddef.h> // For size_t.
#include "include/base/cef_build.h" // For COMPILER_MSVC
// CEF does not use movable types.
#define MOVE_SCOPED_PTR(var) var.Pass()
// CEF uses base types.
#define SCOPED_PTR(type) scoped_ptr<type>
#define DEFAULT_DELETER(type) struct base::DefaultDeleter<type>
#if !defined(arraysize)
// The arraysize(arr) macro returns the # of elements in an array arr.

View File

@ -159,18 +159,18 @@ class CefResourceManager :
// The below methods are called on the browser process IO thread.
explicit Request(SCOPED_PTR(RequestState) state);
explicit Request(scoped_ptr<RequestState> state);
SCOPED_PTR(RequestState) SendRequest();
scoped_ptr<RequestState> SendRequest();
bool HasState();
static void ContinueOnIOThread(SCOPED_PTR(RequestState) state,
static void ContinueOnIOThread(scoped_ptr<RequestState> state,
CefRefPtr<CefResourceHandler> handler);
static void StopOnIOThread(SCOPED_PTR(RequestState) state);
static void StopOnIOThread(scoped_ptr<RequestState> state);
// Will be non-NULL while the request is pending. Only accessed on the
// browser process IO thread.
SCOPED_PTR(RequestState) state_;
scoped_ptr<RequestState> state_;
// Params that stay with this request object. Safe to access on any thread.
RequestParams params_;
@ -343,10 +343,10 @@ class CefResourceManager :
// Methods that manage request state between requests. Called on the browser
// process IO thread.
bool SendRequest(SCOPED_PTR(RequestState) state);
void ContinueRequest(SCOPED_PTR(RequestState) state,
bool SendRequest(scoped_ptr<RequestState> state);
void ContinueRequest(scoped_ptr<RequestState> state,
CefRefPtr<CefResourceHandler> handler);
void StopRequest(SCOPED_PTR(RequestState) state);
void StopRequest(scoped_ptr<RequestState> state);
bool IncrementProvider(RequestState* state);
void DetachRequestFromProvider(RequestState* state);
void GetNextValidProvider(ProviderEntryList::iterator& iterator);
@ -365,7 +365,7 @@ class CefResourceManager :
MimeTypeResolver mime_type_resolver_;
// Must be the last member. Created and accessed on the IO thread.
SCOPED_PTR(base::WeakPtrFactory<CefResourceManager>) weak_ptr_factory_;
scoped_ptr<base::WeakPtrFactory<CefResourceManager> > weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(CefResourceManager);
};

View File

@ -91,7 +91,7 @@ class CefStreamResourceHandler : public CefResourceHandler {
bool read_on_file_thread_;
class Buffer;
SCOPED_PTR(Buffer) buffer_;
scoped_ptr<Buffer> buffer_;
#if DCHECK_IS_ON()
// Used in debug builds to verify that |buffer_| isn't being accessed on
// multiple threads at the same time.

View File

@ -318,7 +318,7 @@ struct CefResourceManager::ProviderEntry {
deletion_pending_(false) {
}
SCOPED_PTR(Provider) provider_;
scoped_ptr<Provider> provider_;
int order_;
std::string identifier_;
@ -378,8 +378,8 @@ void CefResourceManager::Request::Stop() {
base::Passed(&state_)));
}
CefResourceManager::Request::Request(SCOPED_PTR(RequestState) state)
: state_(MOVE_SCOPED_PTR(state)),
CefResourceManager::Request::Request(scoped_ptr<RequestState> state)
: state_(state.Pass()),
params_(state_->params_) {
CEF_REQUIRE_IO_THREAD();
@ -396,13 +396,13 @@ CefResourceManager::Request::Request(SCOPED_PTR(RequestState) state)
// handle the request. Note that |state_| may already be NULL if OnRequest
// executes a callback before returning, in which case execution will continue
// asynchronously in any case.
SCOPED_PTR(CefResourceManager::RequestState)
scoped_ptr<CefResourceManager::RequestState>
CefResourceManager::Request::SendRequest() {
CEF_REQUIRE_IO_THREAD();
Provider* provider = (*state_->current_entry_pos_)->provider_.get();
if (!provider->OnRequest(this))
return MOVE_SCOPED_PTR(state_);
return SCOPED_PTR(RequestState)();
return state_.Pass();
return scoped_ptr<RequestState>();
}
bool CefResourceManager::Request::HasState() {
@ -412,23 +412,23 @@ bool CefResourceManager::Request::HasState() {
// static
void CefResourceManager::Request::ContinueOnIOThread(
SCOPED_PTR(RequestState) state,
scoped_ptr<RequestState> state,
CefRefPtr<CefResourceHandler> handler) {
CEF_REQUIRE_IO_THREAD();
// The manager may already have been deleted.
base::WeakPtr<CefResourceManager> manager = state->manager_;
if (manager)
manager->ContinueRequest(MOVE_SCOPED_PTR(state), handler);
manager->ContinueRequest(state.Pass(), handler);
}
// static
void CefResourceManager::Request::StopOnIOThread(
SCOPED_PTR(RequestState) state) {
scoped_ptr<RequestState> state) {
CEF_REQUIRE_IO_THREAD();
// The manager may already have been deleted.
base::WeakPtr<CefResourceManager> manager = state->manager_;
if (manager)
manager->StopRequest(MOVE_SCOPED_PTR(state));
manager->StopRequest(state.Pass());
}
@ -493,7 +493,7 @@ void CefResourceManager::AddProvider(Provider* provider,
return;
}
SCOPED_PTR(ProviderEntry) new_entry(
scoped_ptr<ProviderEntry> new_entry(
new ProviderEntry(provider, order, identifier));
if (providers_.empty()) {
@ -587,7 +587,7 @@ cef_return_value_t CefResourceManager::OnBeforeResourceLoad(
return RV_CONTINUE;
}
SCOPED_PTR(RequestState) state(new RequestState);
scoped_ptr<RequestState> state(new RequestState);
if (!weak_ptr_factory_.get()) {
// WeakPtrFactory instances need to be created and destroyed on the same
@ -611,7 +611,7 @@ cef_return_value_t CefResourceManager::OnBeforeResourceLoad(
state->current_entry_pos_ = current_entry_pos;
// If the request is potentially handled we need to continue asynchronously.
return SendRequest(MOVE_SCOPED_PTR(state)) ? RV_CONTINUE_ASYNC : RV_CONTINUE;
return SendRequest(state.Pass()) ? RV_CONTINUE_ASYNC : RV_CONTINUE;
}
CefRefPtr<CefResourceHandler> CefResourceManager::GetResourceHandler(
@ -637,13 +637,13 @@ CefRefPtr<CefResourceHandler> CefResourceManager::GetResourceHandler(
// Send the request to providers in order until one potentially handles it or we
// run out of providers. Returns true if the request is potentially handled.
bool CefResourceManager::SendRequest(SCOPED_PTR(RequestState) state) {
bool CefResourceManager::SendRequest(scoped_ptr<RequestState> state) {
bool potentially_handled = false;
do {
// Should not be on the last provider entry.
DCHECK(state->current_entry_pos_ != providers_.end());
scoped_refptr<Request> request = new Request(MOVE_SCOPED_PTR(state));
scoped_refptr<Request> request = new Request(state.Pass());
// Give the provider an opportunity to handle the request.
state = request->SendRequest();
@ -651,7 +651,7 @@ bool CefResourceManager::SendRequest(SCOPED_PTR(RequestState) state) {
// The provider will not handle the request. Move to the next provider if
// any.
if (!IncrementProvider(state.get()))
StopRequest(MOVE_SCOPED_PTR(state));
StopRequest(state.Pass());
} else {
potentially_handled = true;
}
@ -661,7 +661,7 @@ bool CefResourceManager::SendRequest(SCOPED_PTR(RequestState) state) {
}
void CefResourceManager::ContinueRequest(
SCOPED_PTR(RequestState) state,
scoped_ptr<RequestState> state,
CefRefPtr<CefResourceHandler> handler) {
CEF_REQUIRE_IO_THREAD();
@ -669,17 +669,17 @@ void CefResourceManager::ContinueRequest(
// The request has been handled. Associate the request ID with the handler.
pending_handlers_.insert(
std::make_pair(state->params_.request_->GetIdentifier(), handler));
StopRequest(MOVE_SCOPED_PTR(state));
StopRequest(state.Pass());
} else {
// Move to the next provider if any.
if (IncrementProvider(state.get()))
SendRequest(MOVE_SCOPED_PTR(state));
SendRequest(state.Pass());
else
StopRequest(MOVE_SCOPED_PTR(state));
StopRequest(state.Pass());
}
}
void CefResourceManager::StopRequest(SCOPED_PTR(RequestState) state) {
void CefResourceManager::StopRequest(scoped_ptr<RequestState> state) {
CEF_REQUIRE_IO_THREAD();
// Detach from the current provider.

View File

@ -69,7 +69,7 @@ class CefStreamResourceHandler::Buffer {
}
private:
SCOPED_PTR(char[]) buffer_;
scoped_ptr<char[]> buffer_;
int size_;
int bytes_requested_;
int bytes_written_;

View File

@ -57,7 +57,7 @@ class CefZipFile : public CefZipArchive::File {
private:
size_t data_size_;
SCOPED_PTR(unsigned char[]) data_;
scoped_ptr<unsigned char[]> data_;
IMPLEMENT_REFCOUNTING(CefZipFile);
DISALLOW_COPY_AND_ASSIGN(CefZipFile);

View File

@ -51,7 +51,7 @@ class MainMessageLoop {
protected:
// Only allow deletion via scoped_ptr.
friend DEFAULT_DELETER(MainMessageLoop);
friend struct base::DefaultDeleter<MainMessageLoop>;
MainMessageLoop();
virtual ~MainMessageLoop();

View File

@ -23,7 +23,7 @@ class MainMessageLoopExternalPump : public MainMessageLoopStd {
public:
// Creates the singleton instance of this object. Must be called on the main
// application thread.
static SCOPED_PTR(MainMessageLoopExternalPump) Create();
static scoped_ptr<MainMessageLoopExternalPump> Create();
// Returns the singleton instance of this object. Safe to call from any
// thread.
@ -36,7 +36,7 @@ class MainMessageLoopExternalPump : public MainMessageLoopStd {
protected:
// Only allow deletion via scoped_ptr.
friend DEFAULT_DELETER(MainMessageLoopExternalPump);
friend struct base::DefaultDeleter<MainMessageLoopExternalPump>;
// Construct and destruct this object on the main application thread.
MainMessageLoopExternalPump();

View File

@ -99,7 +99,7 @@ class MainMessageLoopExternalPumpLinux : public MainMessageLoopExternalPump {
int wakeup_pipe_write_;
// Use a scoped_ptr to avoid needing the definition of GPollFD in the header.
SCOPED_PTR(GPollFD) wakeup_gpollfd_;
scoped_ptr<GPollFD> wakeup_gpollfd_;
};
// Return a timeout suitable for the glib loop, -1 to block forever,
@ -296,9 +296,9 @@ bool MainMessageLoopExternalPumpLinux::IsTimerPending() {
} // namespace
// static
SCOPED_PTR(MainMessageLoopExternalPump)
scoped_ptr<MainMessageLoopExternalPump>
MainMessageLoopExternalPump::Create() {
return SCOPED_PTR(MainMessageLoopExternalPump)(
return scoped_ptr<MainMessageLoopExternalPump>(
new MainMessageLoopExternalPumpLinux());
}

View File

@ -162,9 +162,9 @@ void MainMessageLoopExternalPumpMac::KillTimer() {
}
// static
SCOPED_PTR(MainMessageLoopExternalPump)
scoped_ptr<MainMessageLoopExternalPump>
MainMessageLoopExternalPump::Create() {
return SCOPED_PTR(MainMessageLoopExternalPump)(
return scoped_ptr<MainMessageLoopExternalPump>(
new MainMessageLoopExternalPumpMac());
}

View File

@ -140,9 +140,9 @@ LRESULT CALLBACK MainMessageLoopExternalPumpWin::WndProc(
} // namespace
// static
SCOPED_PTR(MainMessageLoopExternalPump)
scoped_ptr<MainMessageLoopExternalPump>
MainMessageLoopExternalPump::Create() {
return SCOPED_PTR(MainMessageLoopExternalPump)(
return scoped_ptr<MainMessageLoopExternalPump>(
new MainMessageLoopExternalPumpWin());
}

View File

@ -710,7 +710,7 @@ TEST(CookieTest, ChangeDirectoryGlobal) {
EXPECT_TRUE(manager.get());
std::string cache_path;
CefTestSuite::GetCachePath(cache_path);
CefTestSuite::GetInstance()->GetCachePath(cache_path);
TestChangeDirectory(manager, event, cache_path);
}

View File

@ -3,6 +3,7 @@
// can be found in the LICENSE file.
#include <algorithm>
#include <cmath>
#include <sstream>
#include <string>

View File

@ -11,6 +11,10 @@
#undef Bool
#endif
#if defined(OS_POSIX)
#include <unistd.h>
#endif
#include "include/base/cef_bind.h"
#include "include/cef_app.h"
#include "include/cef_task.h"
@ -31,12 +35,6 @@
namespace {
// Used to track state when running tests on a separate thread.
struct TestState {
CefTestSuite* test_suite_;
int retval_;
};
void QuitMessageLoop() {
client::MainMessageLoop* message_loop = client::MainMessageLoop::Get();
if (message_loop)
@ -45,28 +43,34 @@ void QuitMessageLoop() {
CefQuitMessageLoop();
}
// Called on the test thread.
void RunTestsOnTestThread(TestState* test_state) {
CHECK(test_state);
void sleep(int64 ms) {
#if defined(OS_WIN)
Sleep(ms);
#elif defined(OS_POSIX)
usleep(ms * 1000);
#else
#error Unsupported platform
#endif
}
// Called on the test thread.
void RunTestsOnTestThread() {
// Run the test suite.
test_state->retval_ = test_state->test_suite_->Run();
CefTestSuite::GetInstance()->Run();
// Wait for all browsers to exit.
while (TestHandler::HasBrowser())
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
sleep(100);
// Quit the CEF message loop.
CefPostTask(TID_UI, base::Bind(&QuitMessageLoop));
}
// Called on the UI thread.
void ContinueOnUIThread(TestState* test_state,
CefRefPtr<CefTaskRunner> test_task_runner) {
void ContinueOnUIThread(CefRefPtr<CefTaskRunner> test_task_runner) {
// Run the test suite on the test thread.
test_task_runner->PostTask(
CefCreateClosureTask(base::Bind(&RunTestsOnTestThread,
base::Unretained(test_state))));
CefCreateClosureTask(base::Bind(&RunTestsOnTestThread)));
}
#if defined(OS_LINUX)
@ -90,25 +94,11 @@ int XIOErrorHandlerImpl(Display *display) {
int main(int argc, char* argv[]) {
#if defined(OS_LINUX)
// Create a copy of |argv| on Linux because Chromium mangles the value
// internally (see issue #620).
CefScopedArgArray scoped_arg_array(argc, argv);
char** argv_copy = scoped_arg_array.array();
#else
char** argv_copy = argv;
#endif
// Parse command-line arguments.
CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
#if defined(OS_WIN)
command_line->InitFromString(::GetCommandLineW());
#else
command_line->InitFromArgv(argc, argv);
#endif
// Create the singleton test suite object.
CefTestSuite test_suite(argc, argv);
#if defined(OS_WIN)
if (command_line->HasSwitch("enable-high-dpi-support")) {
if (test_suite.command_line()->HasSwitch("enable-high-dpi-support")) {
// Enable High-DPI support on Windows 7 and newer.
CefEnableHighDPISupport();
}
@ -129,7 +119,7 @@ int main(int argc, char* argv[]) {
// Create a ClientApp of the correct type.
CefRefPtr<CefApp> app;
client::ClientApp::ProcessType process_type =
client::ClientApp::GetProcessType(command_line);
client::ClientApp::GetProcessType(test_suite.command_line());
if (process_type == client::ClientApp::BrowserProcess) {
app = new client::ClientAppBrowser();
} else if (process_type == client::ClientApp::RendererProcess ||
@ -144,11 +134,8 @@ int main(int argc, char* argv[]) {
if (exit_code >= 0)
return exit_code;
// Initialize the CommandLine object.
CefTestSuite::InitCommandLine(argc, argv_copy);
CefSettings settings;
CefTestSuite::GetSettings(settings);
test_suite.GetSettings(settings);
#if defined(OS_MACOSX)
// Platform-specific initialization.
@ -164,7 +151,7 @@ int main(int argc, char* argv[]) {
#endif
// Create the MessageLoop.
std::unique_ptr<client::MainMessageLoop> message_loop;
scoped_ptr<client::MainMessageLoop> message_loop;
if (!settings.multi_threaded_message_loop) {
if (settings.external_message_pump)
message_loop = client::MainMessageLoopExternalPump::Create();
@ -175,8 +162,8 @@ int main(int argc, char* argv[]) {
// Initialize CEF.
CefInitialize(main_args, settings, app, windows_sandbox_info);
// Create the test suite object. TestSuite will modify |argv_copy|.
CefTestSuite test_suite(argc, argv_copy);
// Initialize the testing framework.
test_suite.InitMainProcess();
int retval;
@ -184,9 +171,6 @@ int main(int argc, char* argv[]) {
// Run the test suite on the main thread.
retval = test_suite.Run();
} else {
TestState test_state = {0};
test_state.test_suite_ = &test_suite;
// Create and start the test thread.
CefRefPtr<CefThread> thread = CefThread::CreateThread("test_thread");
if (!thread)
@ -195,14 +179,13 @@ int main(int argc, char* argv[]) {
// Start the tests from the UI thread so that any pending UI tasks get a
// chance to execute first.
CefPostTask(TID_UI,
base::Bind(&ContinueOnUIThread, base::Unretained(&test_state),
thread->GetTaskRunner()));
base::Bind(&ContinueOnUIThread, thread->GetTaskRunner()));
// Run the CEF message loop.
message_loop->Run();
// The test suite has completed.
retval = test_state.retval_;
retval = test_suite.retval();
// Terminate the test thread.
thread->Stop();

View File

@ -1,67 +1,145 @@
// Copyright (c) 2011 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.
// Copyright 2016 The Chromium Embedded Framework Authors. Postions copyright
// 2012 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 "tests/unittests/test_suite.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/test/test_suite.h"
#if defined(OS_MACOSX)
#include "base/debug/stack_trace.h"
#include "base/files/file_path.h"
#include "base/i18n/icu_util.h"
#include "base/path_service.h"
#include "base/test/test_timeouts.h"
#endif
#include "tests/cefclient/common/client_switches.h"
base::CommandLine* CefTestSuite::commandline_ = NULL;
#include "testing/gtest/include/gtest/gtest.h"
CefTestSuite::CefTestSuite(int argc, char** argv)
: TestSuite(argc, argv) {
}
namespace {
// static
void CefTestSuite::InitCommandLine(int argc, const char* const* argv) {
if (commandline_) {
// If this is intentional, Reset() must be called first. If we are using
// the shared build mode, we have to share a single object across multiple
// shared libraries.
CefTestSuite* g_test_suite = nullptr;
#if defined(OS_WIN)
// From base/process/launch_win.cc.
void RouteStdioToConsole(bool create_console_if_not_found) {
// Don't change anything if stdout or stderr already point to a
// valid stream.
//
// If we are running under Buildbot or under Cygwin's default
// terminal (mintty), stderr and stderr will be pipe handles. In
// that case, we don't want to open CONOUT$, because its output
// likely does not go anywhere.
//
// We don't use GetStdHandle() to check stdout/stderr here because
// it can return dangling IDs of handles that were never inherited
// by this process. These IDs could have been reused by the time
// this function is called. The CRT checks the validity of
// stdout/stderr on startup (before the handle IDs can be reused).
// _fileno(stdout) will return -2 (_NO_CONSOLE_FILENO) if stdout was
// invalid.
if (_fileno(stdout) >= 0 || _fileno(stderr) >= 0) {
return;
}
commandline_ = new base::CommandLine(base::CommandLine::NO_PROGRAM);
if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
unsigned int result = GetLastError();
// Was probably already attached.
if (result == ERROR_ACCESS_DENIED)
return;
// Don't bother creating a new console for each child process if the
// parent process is invalid (eg: crashed).
if (result == ERROR_GEN_FAILURE)
return;
if (create_console_if_not_found) {
// Make a new console if attaching to parent fails with any other error.
// It should be ERROR_INVALID_HANDLE at this point, which means the
// browser was likely not started from a console.
AllocConsole();
} else {
return;
}
}
// Arbitrary byte count to use when buffering output lines. More
// means potential waste, less means more risk of interleaved
// log-lines in output.
enum { kOutputBufferSize = 64 * 1024 };
if (freopen("CONOUT$", "w", stdout)) {
setvbuf(stdout, nullptr, _IOLBF, kOutputBufferSize);
// Overwrite FD 1 for the benefit of any code that uses this FD
// directly. This is safe because the CRT allocates FDs 0, 1 and
// 2 at startup even if they don't have valid underlying Windows
// handles. This means we won't be overwriting an FD created by
// _open() after startup.
_dup2(_fileno(stdout), 1);
}
if (freopen("CONOUT$", "w", stderr)) {
setvbuf(stderr, nullptr, _IOLBF, kOutputBufferSize);
_dup2(_fileno(stderr), 2);
}
// Fix all cout, wcout, cin, wcin, cerr, wcerr, clog and wclog.
std::ios::sync_with_stdio();
}
#endif // defined(OS_WIN)
} // namespace
CefTestSuite::CefTestSuite(int argc, char** argv)
: argc_(argc),
argv_(argc, argv),
retval_(0) {
g_test_suite = this;
// Keep a representation of the original command-line.
command_line_ = CefCommandLine::CreateCommandLine();
#if defined(OS_WIN)
commandline_->ParseFromString(::GetCommandLineW());
#elif defined(OS_POSIX)
commandline_->InitFromArgv(argc, argv);
command_line_->InitFromString(::GetCommandLineW());
#else
command_line_->InitFromArgv(argc, argv);
#endif
}
CefTestSuite::~CefTestSuite() {
g_test_suite = nullptr;
}
// static
void CefTestSuite::GetSettings(CefSettings& settings) {
CefTestSuite* CefTestSuite::GetInstance() {
return g_test_suite;
}
void CefTestSuite::InitMainProcess() {
PreInitialize();
// This will modify |argc_| and |argv_|.
testing::InitGoogleTest(&argc_, argv_.array());
}
// Don't add additional code to this method. Instead add it to Initialize().
int CefTestSuite::Run() {
Initialize();
retval_ = RUN_ALL_TESTS();
Shutdown();
return retval_;
}
void CefTestSuite::GetSettings(CefSettings& settings) const {
#if defined(OS_WIN)
settings.multi_threaded_message_loop =
commandline_->HasSwitch(client::switches::kMultiThreadedMessageLoop);
command_line_->HasSwitch(client::switches::kMultiThreadedMessageLoop);
#endif
if (!settings.multi_threaded_message_loop) {
settings.external_message_pump =
commandline_->HasSwitch(client::switches::kExternalMessagePump);
command_line_->HasSwitch(client::switches::kExternalMessagePump);
}
CefString(&settings.cache_path) =
commandline_->GetSwitchValueASCII(client::switches::kCachePath);
command_line_->GetSwitchValue(client::switches::kCachePath);
// Always expose the V8 gc() function to give tests finer-grained control over
// memory management.
std::string javascript_flags = "--expose-gc";
// Value of kJavascriptFlags switch.
std::string other_javascript_flags =
commandline_->GetSwitchValueASCII("js-flags");
command_line_->GetSwitchValue("js-flags");
if (!other_javascript_flags.empty())
javascript_flags += " " + other_javascript_flags;
CefString(&settings.javascript_flags) = javascript_flags;
@ -77,55 +155,40 @@ void CefTestSuite::GetSettings(CefSettings& settings) {
}
// static
bool CefTestSuite::GetCachePath(std::string& path) {
DCHECK(commandline_);
if (commandline_->HasSwitch(client::switches::kCachePath)) {
bool CefTestSuite::GetCachePath(std::string& path) const {
if (command_line_->HasSwitch(client::switches::kCachePath)) {
// Set the cache_path value.
path = commandline_->GetSwitchValueASCII(client::switches::kCachePath);
path = command_line_->GetSwitchValue(client::switches::kCachePath);
return true;
}
return false;
}
#if defined(OS_MACOSX)
void CefTestSuite::Initialize() {
// The below code is copied from base/test/test_suite.cc to avoid calling
// RegisterMockCrApp() on Mac.
void CefTestSuite::PreInitialize() {
#if defined(OS_WIN)
testing::GTEST_FLAG(catch_exceptions) = false;
base::FilePath exe;
PathService::Get(base::FILE_EXE, &exe);
// Initialize logging.
logging::LoggingSettings log_settings;
log_settings.log_file =
exe.ReplaceExtension(FILE_PATH_LITERAL("log")).value().c_str();
log_settings.logging_dest = logging::LOG_TO_ALL;
log_settings.lock_log = logging::LOCK_LOG_FILE;
log_settings.delete_old = logging::DELETE_OLD_LOG_FILE;
logging::InitLogging(log_settings);
// Enable termination on heap corruption.
// Ignore the result code. Supported starting with XP SP3 and Vista.
HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
#endif
// We want process and thread IDs because we may have multiple processes.
// Note: temporarily enabled timestamps in an effort to catch bug 6361.
logging::SetLogItems(true, true, true, true);
#if defined(OS_LINUX) && defined(USE_AURA)
// When calling native char conversion functions (e.g wrctomb) we need to
// have the locale set. In the absence of such a call the "C" locale is the
// default. In the gtk code (below) gtk_init() implicitly sets a locale.
setlocale(LC_ALL, "");
#endif // defined(OS_LINUX) && defined(USE_AURA)
CHECK(base::debug::EnableInProcessStackDumping());
// In some cases, we do not want to see standard error dialogs.
if (!base::debug::BeingDebugged() &&
!base::CommandLine::ForCurrentProcess()->HasSwitch(
"show-error-dialogs")) {
SuppressErrorDialogs();
base::debug::SetSuppressDebugUI(true);
logging::SetLogAssertHandler(UnitTestAssertHandler);
}
base::i18n::InitializeICU();
CatchMaybeTests();
ResetCommandLine();
TestTimeouts::Initialize();
// Don't add additional code to this function. Instead add it to Initialize().
}
#endif // defined(OS_MACOSX)
void CefTestSuite::Initialize() {
#if defined(OS_WIN)
RouteStdioToConsole(true);
#endif // defined(OS_WIN)
}
void CefTestSuite::Shutdown() {
}

View File

@ -1,39 +1,46 @@
// Copyright (c) 2011 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.
// Copyright 2016 The Chromium Embedded Framework Authors. Postions copyright
// 2012 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.
#ifndef CEF_TESTS_UNITTESTS_TEST_SUITE_H_
#define CEF_TESTS_UNITTESTS_TEST_SUITE_H_
#pragma once
#include <string>
#include "include/internal/cef_types_wrappers.h"
#include "base/test/test_suite.h"
namespace base {
class CommandLine;
}
#include "include/cef_command_line.h"
#include "include/wrapper/cef_helpers.h"
class CefTestSuite : public base::TestSuite {
// A single instance of this object will be created by main() in
// run_all_unittests.cc.
class CefTestSuite {
public:
CefTestSuite(int argc, char** argv);
~CefTestSuite();
// Initialize the current process CommandLine singleton. On Windows, ignores
// its arguments (we instead parse GetCommandLineW() directly) because we
// don't trust the CRT's parsing of the command line, but it still must be
// called to set up the command line.
static void InitCommandLine(int argc, const char* const* argv);
static CefTestSuite* GetInstance();
static void GetSettings(CefSettings& settings);
static bool GetCachePath(std::string& path);
void InitMainProcess();
int Run();
protected:
#if defined(OS_MACOSX)
virtual void Initialize();
#endif
void GetSettings(CefSettings& settings) const;
bool GetCachePath(std::string& path) const;
// The singleton CommandLine representing the current process's command line.
static base::CommandLine* commandline_;
CefRefPtr<CefCommandLine> command_line() const { return command_line_; }
// The return value from Run().
int retval() const { return retval_; }
private:
void PreInitialize();
void Initialize();
void Shutdown();
int argc_;
CefScopedArgArray argv_;
CefRefPtr<CefCommandLine> command_line_;
int retval_;
};
#define CEF_SETTINGS_ACCEPT_LANGUAGE "en-GB"

View File

@ -32,7 +32,8 @@ void TestMapNoDuplicates(const CefRequest::HeaderMap& map) {
CefRequest::HeaderMap::const_iterator it2 = it1;
for (++it2; it2 != map.end(); ++it2) {
EXPECT_FALSE(it1->first == it2->first && it1->second == it2->second) <<
"Duplicate entry for " << it1->first << ": " << it1->second;
"Duplicate entry for " << it1->first.ToString() << ": " <<
it1->second.ToString();
}
}
}