Commit ced4e7a9 authored by johnmoore@google.com's avatar johnmoore@google.com

[ChromeDriver] Subscribe PerformanceLogger to CommandListener interface

BUG=

Review URL: https://codereview.chromium.org/353063005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283835 0039d316-1c4b-4281-b951-d872f2087c98
parent c90678e6
......@@ -454,8 +454,6 @@
'test/chromedriver/chrome/mobile_emulation_override_manager.h',
'test/chromedriver/chrome/navigation_tracker.cc',
'test/chromedriver/chrome/navigation_tracker.h',
'test/chromedriver/chrome/performance_logger.h',
'test/chromedriver/chrome/performance_logger.cc',
'test/chromedriver/chrome/status.cc',
'test/chromedriver/chrome/status.h',
'test/chromedriver/chrome/ui_events.cc',
......@@ -596,6 +594,9 @@
'test/chromedriver/capabilities.h',
'test/chromedriver/chrome_launcher.cc',
'test/chromedriver/chrome_launcher.h',
'test/chromedriver/command_listener.h',
'test/chromedriver/command_listener_proxy.cc',
'test/chromedriver/command_listener_proxy.h',
'test/chromedriver/command.h',
'test/chromedriver/commands.cc',
'test/chromedriver/commands.h',
......@@ -612,6 +613,8 @@
'test/chromedriver/keycode_text_conversion_x.cc',
'test/chromedriver/logging.cc',
'test/chromedriver/logging.h',
'test/chromedriver/performance_logger.cc',
'test/chromedriver/performance_logger.h',
'test/chromedriver/server/http_handler.cc',
'test/chromedriver/server/http_handler.h',
'test/chromedriver/session.cc',
......@@ -708,7 +711,6 @@
'test/chromedriver/chrome/javascript_dialog_manager_unittest.cc',
'test/chromedriver/chrome/mobile_emulation_override_manager_unittest.cc',
'test/chromedriver/chrome/navigation_tracker_unittest.cc',
'test/chromedriver/chrome/performance_logger_unittest.cc',
'test/chromedriver/chrome/status_unittest.cc',
'test/chromedriver/chrome/stub_chrome.cc',
'test/chromedriver/chrome/stub_chrome.h',
......@@ -718,8 +720,10 @@
'test/chromedriver/chrome/stub_web_view.h',
'test/chromedriver/chrome/web_view_impl_unittest.cc',
'test/chromedriver/chrome_launcher_unittest.cc',
'test/chromedriver/command_listener_proxy_unittest.cc',
'test/chromedriver/commands_unittest.cc',
'test/chromedriver/logging_unittest.cc',
'test/chromedriver/performance_logger_unittest.cc',
'test/chromedriver/server/http_handler_unittest.cc',
'test/chromedriver/session_commands_unittest.cc',
'test/chromedriver/session_unittest.cc',
......
// Copyright 2014 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 CHROME_TEST_CHROMEDRIVER_COMMAND_LISTENER_H_
#define CHROME_TEST_CHROMEDRIVER_COMMAND_LISTENER_H_
#include <string>
class Status;
class CommandListener {
public:
virtual ~CommandListener() {}
// Called just before a WebDriver command is run, but only
// for commands that operate on an existing session. Will be called for
// WindowCommands, ElementCommands, SessionCommands, and AlertCommands.
virtual Status BeforeCommand(const std::string& command_name) = 0;
};
#endif // CHROME_TEST_CHROMEDRIVER_COMMAND_LISTENER_H_
// Copyright 2014 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 "chrome/test/chromedriver/chrome/devtools_client.h"
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/command_listener_proxy.h"
#include "chrome/test/chromedriver/logging.h"
CommandListenerProxy::CommandListenerProxy(
CommandListener* command_listener) : command_listener_(command_listener) {
CHECK(command_listener_);
}
CommandListenerProxy::~CommandListenerProxy() { }
Status CommandListenerProxy::BeforeCommand(const std::string& command_name) {
return command_listener_->BeforeCommand(command_name);
}
// Copyright 2014 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 CHROME_TEST_CHROMEDRIVER_COMMAND_LISTENER_PROXY_H_
#define CHROME_TEST_CHROMEDRIVER_COMMAND_LISTENER_PROXY_H_
#include <string>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "chrome/test/chromedriver/command_listener.h"
class CommandListenerProxy : public CommandListener {
public:
virtual ~CommandListenerProxy();
// |command_listener| must not be null.
explicit CommandListenerProxy(CommandListener* command_listener);
// Forwards commands to |command_listener_|.
virtual Status BeforeCommand(const std::string& command_name) OVERRIDE;
private:
CommandListener* const command_listener_;
DISALLOW_COPY_AND_ASSIGN(CommandListenerProxy);
};
#endif // CHROME_TEST_CHROMEDRIVER_COMMAND_LISTENER_PROXY_H_
// Copyright 2014 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 <string>
#include "base/compiler_specific.h"
#include "base/values.h"
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/command_listener_proxy.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class MockCommandListener : public CommandListener {
public:
MockCommandListener() : called_(false) {}
virtual ~MockCommandListener() {}
virtual Status BeforeCommand(const std::string& command_name) OVERRIDE {
called_ = true;
EXPECT_STREQ("cmd", command_name.c_str());
return Status(kOk);
}
void VerifyCalled() {
EXPECT_TRUE(called_);
}
void VerifyNotCalled() {
EXPECT_FALSE(called_);
}
private:
bool called_;
};
} // namespace
TEST(CommandListenerProxy, ForwardsCommands) {
MockCommandListener listener;
listener.VerifyNotCalled();
CommandListenerProxy proxy(&listener);
listener.VerifyNotCalled();
ASSERT_EQ(kOk, proxy.BeforeCommand("cmd").code());
listener.VerifyCalled();
}
......@@ -151,6 +151,10 @@ void ExecuteSessionCommandOnSessionThread(
VLOG(0) << "COMMAND " << command_name << " "
<< FormatValueForDisplay(*params);
}
// Notify |session|'s |CommandListener|s of the command.
NotifySessionListenersBeforeCommand(session, command_name);
scoped_ptr<base::Value> value;
Status status = command.Run(session, *params, &value);
......
......@@ -18,6 +18,7 @@
#include "chrome/test/chromedriver/chrome/stub_chrome.h"
#include "chrome/test/chromedriver/chrome/stub_web_view.h"
#include "chrome/test/chromedriver/chrome/web_view.h"
#include "chrome/test/chromedriver/command_listener_proxy.h"
#include "chrome/test/chromedriver/commands.h"
#include "chrome/test/chromedriver/element_commands.h"
#include "chrome/test/chromedriver/session.h"
......@@ -546,3 +547,113 @@ TEST(CommandsTest, ErrorFindChildElement) {
ExecuteFindChildElements(
1, &session, &web_view, element_id, params, &result).code());
}
namespace {
class MockCommandListener : public CommandListener {
public:
MockCommandListener() : called_(false) {}
virtual ~MockCommandListener() {}
virtual Status BeforeCommand(const std::string& command_name) OVERRIDE {
called_ = true;
EXPECT_STREQ("cmd", command_name.c_str());
return Status(kOk);
}
void VerifyCalled() {
EXPECT_TRUE(called_);
}
void VerifyNotCalled() {
EXPECT_FALSE(called_);
}
private:
bool called_;
};
Status ExecuteAddListenerToSessionCommand(
CommandListener* listener,
Session* session,
const base::DictionaryValue& params,
scoped_ptr<base::Value>* return_value) {
session->command_listeners.push_back(listener);
return Status(kOk);
}
Status ExecuteQuitSessionCommand(
Session* session,
const base::DictionaryValue& params,
scoped_ptr<base::Value>* return_value) {
session->quit = true;
return Status(kOk);
}
void OnSessionCommand(
base::RunLoop* run_loop,
const Status& status,
scoped_ptr<base::Value> value,
const std::string& session_id) {
ASSERT_EQ(kOk, status.code());
run_loop->Quit();
}
} // namespace
TEST(CommandsTest, SessionNotifiedOfCommand) {
SessionThreadMap map;
linked_ptr<base::Thread> thread(new base::Thread("1"));
ASSERT_TRUE(thread->Start());
std::string id("id");
thread->message_loop()->PostTask(
FROM_HERE,
base::Bind(&internal::CreateSessionOnSessionThreadForTesting, id));
map[id] = thread;
base::DictionaryValue params;
scoped_ptr<MockCommandListener> listener(new MockCommandListener());
CommandListenerProxy* proxy = new CommandListenerProxy(listener.get());
// We add |proxy| to the session instead of adding |listener| directly so that
// after the session is destroyed by ExecuteQuitSessionCommand, we can still
// verify the listener was called. The session owns and will destroy |proxy|.
SessionCommand cmd = base::Bind(
&ExecuteAddListenerToSessionCommand, proxy);
base::MessageLoop loop;
base::RunLoop run_loop_addlistener;
// |CommandListener|s are notified immediately before commands are run.
// Here, the command adds |listener| to the session, so |listener|
// should not be notified since it will not have been added yet.
ExecuteSessionCommand(
&map,
"cmd",
cmd,
false,
params,
id,
base::Bind(&OnSessionCommand,
&run_loop_addlistener));
run_loop_addlistener.Run();
listener->VerifyNotCalled();
base::RunLoop run_loop_testlistener;
cmd = base::Bind(
&ExecuteQuitSessionCommand);
// |listener| was added to |session| by ExecuteAddListenerToSessionCommand
// and should be notified before the next command, ExecuteQuitSessionCommand.
ExecuteSessionCommand(
&map,
"cmd",
cmd,
false,
params,
id,
base::Bind(&OnSessionCommand,
&run_loop_testlistener));
run_loop_testlistener.Run();
listener->VerifyCalled();
}
......@@ -14,8 +14,9 @@
#include "base/time/time.h"
#include "chrome/test/chromedriver/capabilities.h"
#include "chrome/test/chromedriver/chrome/console_logger.h"
#include "chrome/test/chromedriver/chrome/performance_logger.h"
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/command_listener_proxy.h"
#include "chrome/test/chromedriver/performance_logger.h"
#include "chrome/test/chromedriver/session.h"
#if defined(OS_POSIX)
......@@ -239,9 +240,11 @@ bool InitLogging() {
Status CreateLogs(const Capabilities& capabilities,
ScopedVector<WebDriverLog>* out_logs,
ScopedVector<DevToolsEventListener>* out_listeners) {
ScopedVector<DevToolsEventListener>* out_devtools_listeners,
ScopedVector<CommandListener>* out_command_listeners) {
ScopedVector<WebDriverLog> logs;
ScopedVector<DevToolsEventListener> listeners;
ScopedVector<DevToolsEventListener> devtools_listeners;
ScopedVector<CommandListener> command_listeners;
Log::Level browser_log_level = Log::kWarning;
const LoggingPrefs& prefs = capabilities.logging_prefs;
......@@ -254,7 +257,13 @@ Status CreateLogs(const Capabilities& capabilities,
if (level != Log::kOff) {
WebDriverLog* log = new WebDriverLog(type, Log::kAll);
logs.push_back(log);
listeners.push_back(new PerformanceLogger(log));
PerformanceLogger* perf_log = new PerformanceLogger(log);
// We use a proxy for |perf_log|'s |CommandListener| interface.
// session->chrome will own |perf_log|, and |session| will own |proxy|.
// session->command_listeners (the proxy) will be destroyed first.
CommandListenerProxy* proxy = new CommandListenerProxy(perf_log);
devtools_listeners.push_back(perf_log);
command_listeners.push_back(proxy);
}
} else if (type == WebDriverLog::kBrowserType) {
browser_log_level = level;
......@@ -271,9 +280,10 @@ Status CreateLogs(const Capabilities& capabilities,
logs.push_back(browser_log);
// If the level is OFF, don't even bother listening for DevTools events.
if (browser_log_level != Log::kOff)
listeners.push_back(new ConsoleLogger(browser_log));
devtools_listeners.push_back(new ConsoleLogger(browser_log));
out_logs->swap(logs);
out_listeners->swap(listeners);
out_devtools_listeners->swap(devtools_listeners);
out_command_listeners->swap(command_listeners);
return Status(kOk);
}
......@@ -14,6 +14,7 @@
#include "chrome/test/chromedriver/chrome/log.h"
struct Capabilities;
class CommandListener;
class DevToolsEventListener;
class ListValue;
class Status;
......@@ -64,9 +65,11 @@ class WebDriverLog : public Log {
// Initializes logging system for ChromeDriver. Returns true on success.
bool InitLogging();
// Creates Log's and DevToolsEventListener's based on logging preferences.
// Creates |Log|s, |DevToolsEventListener|s, and |CommandListener|s based on
// logging preferences.
Status CreateLogs(const Capabilities& capabilities,
ScopedVector<WebDriverLog>* out_logs,
ScopedVector<DevToolsEventListener>* out_listeners);
ScopedVector<DevToolsEventListener>* out_devtools_listeners,
ScopedVector<CommandListener>* out_command_listeners);
#endif // CHROME_TEST_CHROMEDRIVER_LOGGING_H_
......@@ -7,6 +7,7 @@
#include "chrome/test/chromedriver/chrome/devtools_event_listener.h"
#include "chrome/test/chromedriver/chrome/log.h"
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/command_listener.h"
#include "chrome/test/chromedriver/logging.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -101,12 +102,15 @@ TEST(Logging, CreatePerformanceLog) {
capabilities.logging_prefs["performance"] = Log::kInfo;
capabilities.logging_prefs["browser"] = Log::kInfo;
ScopedVector<DevToolsEventListener> listeners;
ScopedVector<DevToolsEventListener> devtools_listeners;
ScopedVector<WebDriverLog> logs;
Status status = CreateLogs(capabilities, &logs, &listeners);
ScopedVector<CommandListener> command_listeners;
Status status = CreateLogs(capabilities, &logs, &devtools_listeners,
&command_listeners);
ASSERT_TRUE(status.IsOk());
ASSERT_EQ(2u, logs.size());
ASSERT_EQ(2u, listeners.size());
ASSERT_EQ(2u, devtools_listeners.size());
ASSERT_EQ(1u, command_listeners.size());
ASSERT_EQ("performance", logs[0]->type());
ASSERT_EQ("browser", logs[1]->type());
}
......@@ -115,24 +119,30 @@ TEST(Logging, IgnoreUnknownLogType) {
Capabilities capabilities;
capabilities.logging_prefs["gaga"] = Log::kInfo;
ScopedVector<DevToolsEventListener> listeners;
ScopedVector<DevToolsEventListener> devtools_listeners;
ScopedVector<WebDriverLog> logs;
Status status = CreateLogs(capabilities, &logs, &listeners);
ScopedVector<CommandListener> command_listeners;
Status status = CreateLogs(capabilities, &logs, &devtools_listeners,
&command_listeners);
EXPECT_TRUE(status.IsOk());
ASSERT_EQ(1u, logs.size());
ASSERT_EQ(1u, listeners.size());
ASSERT_EQ(1u, devtools_listeners.size());
ASSERT_EQ(0u, command_listeners.size());
ASSERT_EQ("browser", logs[0]->type());
}
TEST(Logging, DefaultLogs) {
Capabilities capabilities;
ScopedVector<DevToolsEventListener> listeners;
ScopedVector<DevToolsEventListener> devtools_listeners;
ScopedVector<WebDriverLog> logs;
Status status = CreateLogs(capabilities, &logs, &listeners);
ScopedVector<CommandListener> command_listeners;
Status status = CreateLogs(capabilities, &logs, &devtools_listeners,
&command_listeners);
EXPECT_TRUE(status.IsOk());
ASSERT_EQ(1u, logs.size());
ASSERT_EQ(1u, listeners.size());
ASSERT_EQ(1u, devtools_listeners.size());
ASSERT_EQ(0u, command_listeners.size());
ASSERT_EQ("browser", logs[0]->type());
}
......
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Copyright 2014 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 "chrome/test/chromedriver/chrome/performance_logger.h"
#include "chrome/test/chromedriver/performance_logger.h"
#include "base/json/json_writer.h"
#include "base/strings/string_util.h"
......@@ -63,3 +63,8 @@ Status PerformanceLogger::OnEvent(
log_->AddEntry(Log::kInfo, log_message_json);
return Status(kOk);
}
// TODO(johnmoore): Use BeforeCommand to implement tracing log.
Status PerformanceLogger::BeforeCommand(const std::string& command_name) {
return Status(kOk);
}
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Copyright 2014 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 CHROME_TEST_CHROMEDRIVER_CHROME_PERFORMANCE_LOGGER_H_
#define CHROME_TEST_CHROMEDRIVER_CHROME_PERFORMANCE_LOGGER_H_
#ifndef CHROME_TEST_CHROMEDRIVER_PERFORMANCE_LOGGER_H_
#define CHROME_TEST_CHROMEDRIVER_PERFORMANCE_LOGGER_H_
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "chrome/test/chromedriver/chrome/devtools_event_listener.h"
#include "chrome/test/chromedriver/command_listener.h"
class Log;
......@@ -18,7 +19,7 @@ class Log;
// "webview": <originating WebView ID>,
// "message": { "method": "...", "params": { ... }} // DevTools message.
// }
class PerformanceLogger : public DevToolsEventListener {
class PerformanceLogger : public DevToolsEventListener, public CommandListener {
public:
// Creates a PerformanceLogger that creates entries in the given Log object.
// The log is owned elsewhere and must not be null.
......@@ -31,10 +32,12 @@ class PerformanceLogger : public DevToolsEventListener {
const std::string& method,
const base::DictionaryValue& params) OVERRIDE;
virtual Status BeforeCommand(const std::string& command_name) OVERRIDE;
private:
Log* log_; // The log where to create entries.
DISALLOW_COPY_AND_ASSIGN(PerformanceLogger);
};
#endif // CHROME_TEST_CHROMEDRIVER_CHROME_PERFORMANCE_LOGGER_H_
#endif // CHROME_TEST_CHROMEDRIVER_PERFORMANCE_LOGGER_H_
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Copyright 2014 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 "chrome/test/chromedriver/chrome/performance_logger.h"
#include "chrome/test/chromedriver/performance_logger.h"
#include "base/compiler_specific.h"
#include "base/format_macros.h"
......
......@@ -16,6 +16,7 @@
#include "chrome/test/chromedriver/basic_types.h"
#include "chrome/test/chromedriver/chrome/device_metrics.h"
#include "chrome/test/chromedriver/chrome/geoposition.h"
#include "chrome/test/chromedriver/command_listener.h"
namespace base {
class DictionaryValue;
......@@ -77,6 +78,11 @@ struct Session {
base::ScopedTempDir temp_dir;
scoped_ptr<base::DictionaryValue> capabilities;
bool auto_reporting_enabled;
// |command_listeners| should be declared after |chrome|. When the |Session|
// is destroyed, |command_listeners| should be freed first, since some
// |CommandListener|s might be |CommandListenerProxy|s that forward to
// |DevToolsEventListener|s owned by |chrome|.
ScopedVector<CommandListener> command_listeners;
};
Session* GetThreadLocalSession();
......
......@@ -28,6 +28,7 @@
#include "chrome/test/chromedriver/chrome/version.h"
#include "chrome/test/chromedriver/chrome/web_view.h"
#include "chrome/test/chromedriver/chrome_launcher.h"
#include "chrome/test/chromedriver/command_listener.h"
#include "chrome/test/chromedriver/logging.h"
#include "chrome/test/chromedriver/net/url_request_context_getter.h"
#include "chrome/test/chromedriver/session.h"
......@@ -124,13 +125,18 @@ Status InitSessionHelper(
// Create Log's and DevToolsEventListener's for ones that are DevTools-based.
// Session will own the Log's, Chrome will own the listeners.
// Also create |CommandListener|s for the appropriate logs.
ScopedVector<DevToolsEventListener> devtools_event_listeners;
ScopedVector<CommandListener> command_listeners;
status = CreateLogs(capabilities,
&session->devtools_logs,
&devtools_event_listeners);
&devtools_event_listeners, &command_listeners);
if (status.IsError())
return status;
// |session| will own the |CommandListener|s.
session->command_listeners.swap(command_listeners);
status = LaunchChrome(bound_params.context_getter.get(),
bound_params.socket_factory,
bound_params.device_manager,
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <list>
#include <string>
#include "base/memory/scoped_ptr.h"
......
......@@ -9,6 +9,7 @@
#include "base/files/file_enumerator.h"
#include "base/files/scoped_temp_dir.h"
#include "base/format_macros.h"
#include "base/memory/scoped_vector.h"
#include "base/rand_util.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
......@@ -18,7 +19,9 @@
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/chrome/ui_events.h"
#include "chrome/test/chromedriver/chrome/web_view.h"
#include "chrome/test/chromedriver/command_listener.h"
#include "chrome/test/chromedriver/key_converter.h"
#include "chrome/test/chromedriver/session.h"
#include "third_party/zlib/google/zip.h"
std::string GenerateId() {
......@@ -401,3 +404,15 @@ Status UnzipSoleFile(const base::FilePath& unzip_dir,
*file = first_file;
return Status(kOk);
}
void NotifySessionListenersBeforeCommand(Session* session,
const std::string& command_name) {
for (ScopedVector<CommandListener>::const_iterator it =
session->command_listeners.begin();
it != session->command_listeners.end();
++it) {
Status status = (*it)->BeforeCommand(command_name);
if (status.IsError())
LOG(ERROR) << "Error when notifying listener of command";
}
}
......@@ -12,6 +12,7 @@ class FilePath;
class ListValue;
}
struct Session;
class Status;
class WebView;
......@@ -39,4 +40,8 @@ Status UnzipSoleFile(const base::FilePath& unzip_dir,
const std::string& bytes,
base::FilePath* file);
// Calls BeforeCommand for each of |session|'s |CommandListener|s.
void NotifySessionListenersBeforeCommand(Session* session,
const std::string& command_name);
#endif // CHROME_TEST_CHROMEDRIVER_UTIL_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment