Commit 2230e1f9 authored by joedow's avatar joedow Committed by Commit bot

Adding Test Fixture for initial test cases for the App Remoting Test Driver. ...

Adding Test Fixture for initial test cases for the App Remoting Test Driver.  Also includes the public stubs for the remote application data methods.

Also ran clang-format on edited files to keep consistent with formatting
in my previous changelist.

BUG=467200

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

Cr-Commit-Position: refs/heads/master@{#322119}
parent a73fbeaa
...@@ -28,6 +28,7 @@ source_set("test_support") { ...@@ -28,6 +28,7 @@ source_set("test_support") {
"test/access_token_fetcher.h", "test/access_token_fetcher.h",
"test/app_remoting_test_driver_environment.cc", "test/app_remoting_test_driver_environment.cc",
"test/app_remoting_test_driver_environment.h", "test/app_remoting_test_driver_environment.h",
"test/app_remoting_test_driver_environment_app_details.cc",
"test/fake_access_token_fetcher.cc", "test/fake_access_token_fetcher.cc",
"test/fake_access_token_fetcher.h", "test/fake_access_token_fetcher.h",
"test/fake_network_dispatcher.cc", "test/fake_network_dispatcher.cc",
...@@ -46,6 +47,7 @@ source_set("test_support") { ...@@ -46,6 +47,7 @@ source_set("test_support") {
"test/mock_access_token_fetcher.h", "test/mock_access_token_fetcher.h",
"test/refresh_token_store.cc", "test/refresh_token_store.cc",
"test/refresh_token_store.h", "test/refresh_token_store.h",
"test/remote_application_details.h",
"test/remote_connection_observer.h", "test/remote_connection_observer.h",
"test/remote_host_info.cc", "test/remote_host_info.cc",
"test/remote_host_info.h", "test/remote_host_info.h",
......
...@@ -31,10 +31,23 @@ ...@@ -31,10 +31,23 @@
], ],
'sources': [ 'sources': [
'test/access_token_fetcher.cc', 'test/access_token_fetcher.cc',
'test/access_token_fetcher.h',
'test/app_remoting_connected_client_fixture.cc',
'test/app_remoting_connected_client_fixture.h',
'test/app_remoting_test_driver_environment.cc', 'test/app_remoting_test_driver_environment.cc',
'test/app_remoting_test_driver_environment.h',
'test/refresh_token_store.cc', 'test/refresh_token_store.cc',
'test/refresh_token_store.h',
'test/remote_application_details.h',
'test/remote_connection_observer.h',
'test/remote_host_info.cc', 'test/remote_host_info.cc',
'test/remote_host_info.h',
'test/remote_host_info_fetcher.cc', 'test/remote_host_info_fetcher.cc',
'test/remote_host_info_fetcher.h',
'test/test_chromoting_client.cc',
'test/test_chromoting_client.h',
'test/test_video_renderer.cc',
'test/test_video_renderer.h',
], ],
}, # end of target 'ar_test_driver_common' }, # end of target 'ar_test_driver_common'
{ {
...@@ -49,6 +62,7 @@ ...@@ -49,6 +62,7 @@
], ],
'sources': [ 'sources': [
'test/app_remoting_test_driver.cc', 'test/app_remoting_test_driver.cc',
'test/app_remoting_test_driver_environment_app_details.cc',
], ],
'include_dirs': [ 'include_dirs': [
'../testing/gtest/include', '../testing/gtest/include',
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
'../remoting/remoting.gyp:remoting_webapp', '../remoting/remoting.gyp:remoting_webapp',
'../remoting/remoting.gyp:remoting_webapp_html', '../remoting/remoting.gyp:remoting_webapp_html',
'../remoting/remoting.gyp:remoting_webapp_unittests', '../remoting/remoting.gyp:remoting_webapp_unittests',
'../remoting/app_remoting_test.gyp:ar_sample_test_driver',
'../remoting/app_remoting_webapp.gyp:ar_sample_app', '../remoting/app_remoting_webapp.gyp:ar_sample_app',
], ],
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
'test/access_token_fetcher.cc', 'test/access_token_fetcher.cc',
'test/access_token_fetcher.h', 'test/access_token_fetcher.h',
'test/app_remoting_test_driver_environment.cc', 'test/app_remoting_test_driver_environment.cc',
'test/app_remoting_test_driver_environment_app_details.cc',
'test/app_remoting_test_driver_environment.h', 'test/app_remoting_test_driver_environment.h',
'test/fake_access_token_fetcher.cc', 'test/fake_access_token_fetcher.cc',
'test/fake_access_token_fetcher.h', 'test/fake_access_token_fetcher.h',
...@@ -68,6 +69,7 @@ ...@@ -68,6 +69,7 @@
'test/mock_access_token_fetcher.h', 'test/mock_access_token_fetcher.h',
'test/refresh_token_store.cc', 'test/refresh_token_store.cc',
'test/refresh_token_store.h', 'test/refresh_token_store.h',
'test/remote_application_details.h',
'test/remote_connection_observer.h', 'test/remote_connection_observer.h',
'test/remote_host_info.cc', 'test/remote_host_info.cc',
'test/remote_host_info.h', 'test/remote_host_info.h',
......
...@@ -21,26 +21,6 @@ const int kMaxGetTokensRetries = 3; ...@@ -21,26 +21,6 @@ const int kMaxGetTokensRetries = 3;
const char kOauthRedirectUrl[] = const char kOauthRedirectUrl[] =
"https://chromoting-oauth.talkgadget." "https://chromoting-oauth.talkgadget."
"google.com/talkgadget/oauth/chrome-remote-desktop/dev"; "google.com/talkgadget/oauth/chrome-remote-desktop/dev";
// Factory function used to initialize our scope vector below, this is needed
// because initializer lists are only supported on C++11 compilers.
const std::vector<std::string> MakeAppRemotingScopeVector() {
std::vector<std::string> app_remoting_scopes;
// Populate the vector with the required permissions for app remoting.
app_remoting_scopes.push_back(
"https://www.googleapis.com/auth/appremoting.runapplication");
app_remoting_scopes.push_back("https://www.googleapis.com/auth/googletalk");
app_remoting_scopes.push_back(
"https://www.googleapis.com/auth/userinfo.email");
app_remoting_scopes.push_back("https://docs.google.com/feeds");
app_remoting_scopes.push_back("https://www.googleapis.com/auth/drive");
return app_remoting_scopes;
}
const std::vector<std::string> kAppRemotingScopeVector =
MakeAppRemotingScopeVector();
} // namespace } // namespace
namespace remoting { namespace remoting {
...@@ -93,7 +73,7 @@ void AccessTokenFetcher::GetAccessTokenFromRefreshToken( ...@@ -93,7 +73,7 @@ void AccessTokenFetcher::GetAccessTokenFromRefreshToken(
auth_client_->RefreshToken( auth_client_->RefreshToken(
oauth_client_info_, oauth_client_info_,
refresh_token_, refresh_token_,
kAppRemotingScopeVector, std::vector<std::string>(), // scopes
kMaxGetTokensRetries, kMaxGetTokensRetries,
this); // GaiaOAuthClient::Delegate* delegate this); // GaiaOAuthClient::Delegate* delegate
} }
...@@ -162,7 +142,6 @@ void AccessTokenFetcher::OnGetTokenInfoResponse( ...@@ -162,7 +142,6 @@ void AccessTokenFetcher::OnGetTokenInfoResponse(
token_info->GetString("error_description", &error_description); token_info->GetString("error_description", &error_description);
LOG(ERROR) << "OnGetTokenInfoResponse returned an error. " LOG(ERROR) << "OnGetTokenInfoResponse returned an error. "
<< ", "
<< "error: " << error_string << ", " << "error: " << error_string << ", "
<< "description: " << error_description; << "description: " << error_description;
access_token_.clear(); access_token_.clear();
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef REMOTING_TEST_ACCESS_TOKEN_FETCHER_H_ #ifndef REMOTING_TEST_ACCESS_TOKEN_FETCHER_H_
#define REMOTING_TEST_ACCESS_TOKEN_FETCHER_H_ #define REMOTING_TEST_ACCESS_TOKEN_FETCHER_H_
#include <string>
#include "base/callback.h" #include "base/callback.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
......
// Copyright 2015 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 "remoting/test/app_remoting_connected_client_fixture.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/run_loop.h"
#include "base/thread_task_runner_handle.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "remoting/protocol/host_stub.h"
#include "remoting/test/app_remoting_test_driver_environment.h"
#include "remoting/test/remote_application_details.h"
#include "remoting/test/test_chromoting_client.h"
namespace {
const int kDefaultDPI = 96;
const int kDefaultWidth = 1024;
const int kDefaultHeight = 768;
const char kHostProcessWindowTitle[] = "Host Process";
void SimpleHostMessageHandler(
const std::string& target_message_type,
const std::string& target_message_data,
const base::Closure& done_closure,
bool* message_received,
const remoting::protocol::ExtensionMessage& message) {
if (message.type() == target_message_type &&
message.data() == target_message_data) {
*message_received = true;
done_closure.Run();
}
}
} // namespace
namespace remoting {
namespace test {
AppRemotingConnectedClientFixture::AppRemotingConnectedClientFixture()
: application_details_(
AppRemotingSharedData->GetDetailsFromAppName(GetParam())),
connection_is_ready_for_tests_(false),
timer_(new base::Timer(true, false)) {
}
AppRemotingConnectedClientFixture::~AppRemotingConnectedClientFixture() {
}
void AppRemotingConnectedClientFixture::SetUp() {
message_loop_.reset(new base::MessageLoopForIO);
client_.reset(new TestChromotingClient());
client_->AddRemoteConnectionObserver(this);
StartConnection();
if (!connection_is_ready_for_tests_) {
FAIL() << "Remote host connection could not be established.";
client_->EndConnection();
}
}
void AppRemotingConnectedClientFixture::TearDown() {
// |client_| must be destroyed before |message_loop_| as some of its
// members are destroyed via DeleteSoon on the message loop's TaskRunner.
client_->RemoveRemoteConnectionObserver(this);
client_.reset();
base::RunLoop().RunUntilIdle();
message_loop_.reset();
}
bool AppRemotingConnectedClientFixture::VerifyResponseForSimpleHostMessage(
const std::string& message_request_title,
const std::string& message_response_title,
const std::string& message_payload,
const base::TimeDelta& max_wait_time) {
DCHECK(thread_checker_.CalledOnValidThread());
bool message_received = false;
DCHECK(!run_loop_ || !run_loop_->running());
run_loop_.reset(new base::RunLoop());
host_message_received_callback_ =
base::Bind(&SimpleHostMessageHandler, message_response_title,
message_payload, run_loop_->QuitClosure(), &message_received);
protocol::ExtensionMessage message;
message.set_type(message_request_title);
message.set_data(message_payload);
client_->host_stub()->DeliverClientMessage(message);
DCHECK(!timer_->IsRunning());
timer_->Start(FROM_HERE, max_wait_time, run_loop_->QuitClosure());
run_loop_->Run();
timer_->Stop();
host_message_received_callback_.Reset();
return message_received;
}
void AppRemotingConnectedClientFixture::StartConnection() {
DCHECK(thread_checker_.CalledOnValidThread());
RemoteHostInfo remote_host_info;
remoting::test::AppRemotingSharedData->GetRemoteHostInfoForApplicationId(
application_details_.application_id, &remote_host_info);
if (!remote_host_info.IsReadyForConnection()) {
LOG(ERROR) << "Remote Host is unavailable for connections.";
return;
}
DCHECK(!run_loop_ || !run_loop_->running());
run_loop_.reset(new base::RunLoop());
// We will wait up to 30 seconds to complete the remote connection and for the
// main application window to become visible.
DCHECK(!timer_->IsRunning());
timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(30),
run_loop_->QuitClosure());
client_->StartConnection(AppRemotingSharedData->user_name(),
AppRemotingSharedData->access_token(),
remote_host_info);
run_loop_->Run();
timer_->Stop();
}
void AppRemotingConnectedClientFixture::ConnectionStateChanged(
protocol::ConnectionToHost::State state,
protocol::ErrorCode error_code) {
DCHECK(thread_checker_.CalledOnValidThread());
// If the connection is closed or failed then mark the connection as closed
// and quit the current RunLoop if it exists.
if (state == protocol::ConnectionToHost::CLOSED ||
state == protocol::ConnectionToHost::FAILED ||
error_code != protocol::OK) {
connection_is_ready_for_tests_ = false;
if (run_loop_) {
run_loop_->Quit();
}
}
}
void AppRemotingConnectedClientFixture::ConnectionReady(bool ready) {
DCHECK(thread_checker_.CalledOnValidThread());
if (ready) {
SendClientConnectionDetailsToHost();
} else {
// We will only get called here with a false value for |ready| if the video
// renderer encounters an error.
connection_is_ready_for_tests_ = false;
if (run_loop_) {
run_loop_->Quit();
}
}
}
void AppRemotingConnectedClientFixture::HostMessageReceived(
const protocol::ExtensionMessage& message) {
DCHECK(thread_checker_.CalledOnValidThread());
// If a callback is not registered, then the message is passed to a default
// handler for the class based on the message type.
if (!host_message_received_callback_.is_null()) {
host_message_received_callback_.Run(message);
} else if (message.type() == "onWindowAdded") {
HandleOnWindowAddedMessage(message);
} else {
DVLOG(2) << "HostMessage not handled by HostMessageReceived().";
DVLOG(2) << "type: " << message.type();
DVLOG(2) << "data: " << message.data();
}
}
void AppRemotingConnectedClientFixture::SendClientConnectionDetailsToHost() {
// First send an access token which will be used for Google Drive access.
protocol::ExtensionMessage message;
message.set_type("accessToken");
message.set_data(AppRemotingSharedData->access_token());
DVLOG(1) << "Sending access token to host";
client_->host_stub()->DeliverClientMessage(message);
// Next send the host a description of the client screen size.
protocol::ClientResolution client_resolution;
client_resolution.set_width(kDefaultWidth);
client_resolution.set_height(kDefaultHeight);
client_resolution.set_x_dpi(kDefaultDPI);
client_resolution.set_y_dpi(kDefaultDPI);
client_resolution.set_dips_width(kDefaultWidth);
client_resolution.set_dips_height(kDefaultHeight);
DVLOG(1) << "Sending ClientResolution details to host";
client_->host_stub()->NotifyClientResolution(client_resolution);
// Finally send a message to start sending us video packets.
protocol::VideoControl video_control;
video_control.set_enable(true);
DVLOG(1) << "Sending enable VideoControl message to host";
client_->host_stub()->ControlVideo(video_control);
}
void AppRemotingConnectedClientFixture::HandleOnWindowAddedMessage(
const remoting::protocol::ExtensionMessage& message) {
DCHECK_EQ(message.type(), "onWindowAdded");
const base::DictionaryValue* message_data = nullptr;
scoped_ptr<base::Value> host_message(base::JSONReader::Read(message.data()));
if (!host_message.get() || !host_message->GetAsDictionary(&message_data)) {
LOG(ERROR) << "onWindowAdded message received was not valid JSON.";
if (run_loop_) {
run_loop_->Quit();
}
return;
}
std::string current_window_title;
message_data->GetString("title", &current_window_title);
if (current_window_title == kHostProcessWindowTitle) {
LOG(ERROR) << "Host Process Window is visible, this likely means that the "
<< "underlying application is in a bad state, YMMV.";
}
std::string main_window_title = application_details_.main_window_title;
if (current_window_title.find_first_of(main_window_title) == 0) {
connection_is_ready_for_tests_ = true;
if (timer_->IsRunning()) {
timer_->Stop();
}
DCHECK(run_loop_);
// Now that the main window is visible, give the app some time to settle
// before signaling that it is ready to run tests.
timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(2),
run_loop_->QuitClosure());
}
}
} // namespace test
} // namespace remoting
// Copyright 2015 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 REMOTING_TEST_APP_REMOTING_CONNECTED_CLIENT_FIXTURE_H_
#define REMOTING_TEST_APP_REMOTING_CONNECTED_CLIENT_FIXTURE_H_
#include <string>
#include "base/callback_forward.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
#include "remoting/test/remote_connection_observer.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
class MessageLoopForIO;
class RunLoop;
class Timer;
}
namespace remoting {
namespace test {
struct RemoteApplicationDetails;
class TestChromotingClient;
// Allows for custom handling of ExtensionMessage messages.
typedef base::Callback<void(const protocol::ExtensionMessage& message)>
HostMessageReceivedCallback;
// Creates a connection to a remote host which is available for tests to use.
// All callbacks must occur on the same thread the object was created on.
class AppRemotingConnectedClientFixture
: public testing::TestWithParam<const char*>,
public RemoteConnectionObserver {
public:
AppRemotingConnectedClientFixture();
~AppRemotingConnectedClientFixture() override;
protected:
// Sends the request to the host and waits for a reply up to |max_wait_time|.
// Returns true if we received a response within the maximum time limit.
bool VerifyResponseForSimpleHostMessage(
const std::string& message_request_title,
const std::string& message_response_title,
const std::string& message_payload,
const base::TimeDelta& max_wait_time);
private:
// testing::Test interface.
void SetUp() override;
void TearDown() override;
// RemoteConnectionObserver interface.
void ConnectionStateChanged(protocol::ConnectionToHost::State state,
protocol::ErrorCode error_code) override;
void ConnectionReady(bool ready) override;
void HostMessageReceived(const protocol::ExtensionMessage& message) override;
// Starts a connection with the remote host.
void StartConnection();
// Sends client details to the host in order to complete the connection.
void SendClientConnectionDetailsToHost();
// Handles onWindowAdded messages from the host.
void HandleOnWindowAddedMessage(
const remoting::protocol::ExtensionMessage& message);
// Contains the details for the application being tested.
const RemoteApplicationDetails& application_details_;
// Called when an ExtensionMessage is received from the host. Used to
// override default message handling.
HostMessageReceivedCallback host_message_received_callback_;
// Indicates whether the remote connection is ready to be used for testing.
// True when a chromoting connection to the remote host has been established
// and the main application window is visible.
bool connection_is_ready_for_tests_;
// Used to post tasks by |client_| and tests.
scoped_ptr<base::MessageLoopForIO> message_loop_;
// Used to run the thread's message loop.
scoped_ptr<base::RunLoop> run_loop_;
// Used for setting timeouts and delays.
scoped_ptr<base::Timer> timer_;
// Used to ensure RemoteConnectionObserver methods are called on the same
// thread.
base::ThreadChecker thread_checker_;
// Creates and manages the connection to the remote host.
scoped_ptr<TestChromotingClient> client_;
DISALLOW_COPY_AND_ASSIGN(AppRemotingConnectedClientFixture);
};
} // namespace test
} // namespace remoting
#endif // REMOTING_TEST_APP_REMOTING_CONNECTED_CLIENT_FIXTURE_H_
...@@ -19,6 +19,7 @@ const char kAuthCodeSwitchName[] = "authcode"; ...@@ -19,6 +19,7 @@ const char kAuthCodeSwitchName[] = "authcode";
const char kHelpSwitchName[] = "help"; const char kHelpSwitchName[] = "help";
const char kLoggingLevelSwitchName[] = "verbosity"; const char kLoggingLevelSwitchName[] = "verbosity";
const char kServiceEnvironmentSwitchName[] = "environment"; const char kServiceEnvironmentSwitchName[] = "environment";
const char kShowHostAvailabilitySwitchName[] = "show-host-availability";
const char kSingleProcessTestsSwitchName[] = "single-process-tests"; const char kSingleProcessTestsSwitchName[] = "single-process-tests";
const char kUserNameSwitchName[] = "username"; const char kUserNameSwitchName[] = "username";
} }
...@@ -68,10 +69,12 @@ void PrintUsage() { ...@@ -68,10 +69,12 @@ void PrintUsage() {
switches::kHelpSwitchName); switches::kHelpSwitchName);
printf(" %s: Specifies the service api to use (dev|test) [default: dev]\n", printf(" %s: Specifies the service api to use (dev|test) [default: dev]\n",
switches::kServiceEnvironmentSwitchName); switches::kServiceEnvironmentSwitchName);
printf( printf(" %s: Retrieves and displays the connection status for all known "
" %s: Specifies the optional logging level of the tool (0-3)." "hosts, no tests will be run\n",
" [default: off]\n", switches::kShowHostAvailabilitySwitchName);
switches::kLoggingLevelSwitchName); printf(" %s: Specifies the optional logging level of the tool (0-3)."
" [default: off]\n",
switches::kLoggingLevelSwitchName);
} }
void PrintAuthCodeInfo() { void PrintAuthCodeInfo() {
...@@ -105,8 +108,7 @@ void PrintAuthCodeInfo() { ...@@ -105,8 +108,7 @@ void PrintAuthCodeInfo() {
printf("\nTool usage example with the newly created auth code:\n"); printf("\nTool usage example with the newly created auth code:\n");
printf("ar_test_driver --%s=example@gmail.com --%s=4/AKtf...\n\n", printf("ar_test_driver --%s=example@gmail.com --%s=4/AKtf...\n\n",
switches::kUserNameSwitchName, switches::kUserNameSwitchName, switches::kAuthCodeSwitchName);
switches::kAuthCodeSwitchName);
} }
} // namespace } // namespace
...@@ -139,8 +141,7 @@ int main(int argc, char** argv) { ...@@ -139,8 +141,7 @@ int main(int argc, char** argv) {
PrintUsage(); PrintUsage();
PrintAuthCodeInfo(); PrintAuthCodeInfo();
return base::LaunchUnitTestsSerially( return base::LaunchUnitTestsSerially(
argc, argc, argv,
argv,
base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite))); base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
} }
...@@ -182,7 +183,7 @@ int main(int argc, char** argv) { ...@@ -182,7 +183,7 @@ int main(int argc, char** argv) {
// Update the logging verbosity level is user specified one. // Update the logging verbosity level is user specified one.
std::string verbosity_level; std::string verbosity_level;
verbosity_level = verbosity_level =
command_line->GetSwitchValueASCII(switches::kLoggingLevelSwitchName); command_line->GetSwitchValueASCII(switches::kLoggingLevelSwitchName);
if (!verbosity_level.empty()) { if (!verbosity_level.empty()) {
// Turn on logging for the test_driver and remoting components. // Turn on logging for the test_driver and remoting components.
// This switch is parsed during logging::InitLogging. // This switch is parsed during logging::InitLogging.
...@@ -206,6 +207,13 @@ int main(int argc, char** argv) { ...@@ -206,6 +207,13 @@ int main(int argc, char** argv) {
return -1; return -1;
} }
if (command_line->HasSwitch(switches::kShowHostAvailabilitySwitchName)) {
// When this flag is specified, we will retrieve connection information
// for all known applications and report the status. No tests will be run.
shared_data->ShowHostAvailability();
return 0;
}
// Since we've successfully set up our shared_data object, we'll assign the // Since we've successfully set up our shared_data object, we'll assign the
// value to our global* and transfer ownership to the framework. // value to our global* and transfer ownership to the framework.
remoting::test::AppRemotingSharedData = shared_data.release(); remoting::test::AppRemotingSharedData = shared_data.release();
...@@ -214,7 +222,6 @@ int main(int argc, char** argv) { ...@@ -214,7 +222,6 @@ int main(int argc, char** argv) {
// Because many tests may access the same remoting host(s), we need to run // Because many tests may access the same remoting host(s), we need to run
// the tests sequentially so they do not interfere with each other. // the tests sequentially so they do not interfere with each other.
return base::LaunchUnitTestsSerially( return base::LaunchUnitTestsSerially(
argc, argc, argv,
argv,
base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite))); base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
} }
...@@ -4,11 +4,16 @@ ...@@ -4,11 +4,16 @@
#include "remoting/test/app_remoting_test_driver_environment.h" #include "remoting/test/app_remoting_test_driver_environment.h"
#include <map>
#include <string>
#include <vector>
#include "base/bind.h" #include "base/bind.h"
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "remoting/test/access_token_fetcher.h" #include "remoting/test/access_token_fetcher.h"
#include "remoting/test/refresh_token_store.h" #include "remoting/test/refresh_token_store.h"
#include "remoting/test/remote_host_info.h" #include "remoting/test/remote_host_info.h"
...@@ -28,6 +33,9 @@ AppRemotingTestDriverEnvironment::AppRemotingTestDriverEnvironment( ...@@ -28,6 +33,9 @@ AppRemotingTestDriverEnvironment::AppRemotingTestDriverEnvironment(
test_remote_host_info_fetcher_(nullptr) { test_remote_host_info_fetcher_(nullptr) {
DCHECK(!user_name_.empty()); DCHECK(!user_name_.empty());
DCHECK(service_environment < kUnknownEnvironment); DCHECK(service_environment < kUnknownEnvironment);
PopulateApplicationNames();
PopulateApplicationDetailsMap();
} }
AppRemotingTestDriverEnvironment::~AppRemotingTestDriverEnvironment() { AppRemotingTestDriverEnvironment::~AppRemotingTestDriverEnvironment() {
...@@ -99,11 +107,9 @@ bool AppRemotingTestDriverEnvironment::GetRemoteHostInfoForApplicationId( ...@@ -99,11 +107,9 @@ bool AppRemotingTestDriverEnvironment::GetRemoteHostInfoForApplicationId(
base::RunLoop run_loop; base::RunLoop run_loop;
RemoteHostInfoCallback remote_host_info_fetch_callback = RemoteHostInfoCallback remote_host_info_fetch_callback = base::Bind(
base::Bind(&AppRemotingTestDriverEnvironment::OnRemoteHostInfoRetrieved, &AppRemotingTestDriverEnvironment::OnRemoteHostInfoRetrieved,
base::Unretained(this), base::Unretained(this), run_loop.QuitClosure(), remote_host_info);
run_loop.QuitClosure(),
remote_host_info);
// If a unit test has set |test_remote_host_info_fetcher_| then we should use // If a unit test has set |test_remote_host_info_fetcher_| then we should use
// it below. Note that we do not want to destroy the test object at the end // it below. Note that we do not want to destroy the test object at the end
...@@ -117,9 +123,7 @@ bool AppRemotingTestDriverEnvironment::GetRemoteHostInfoForApplicationId( ...@@ -117,9 +123,7 @@ bool AppRemotingTestDriverEnvironment::GetRemoteHostInfoForApplicationId(
} }
remote_host_info_fetcher->RetrieveRemoteHostInfo( remote_host_info_fetcher->RetrieveRemoteHostInfo(
application_id, application_id, access_token_, service_environment_,
access_token_,
service_environment_,
remote_host_info_fetch_callback); remote_host_info_fetch_callback);
run_loop.Run(); run_loop.Run();
...@@ -127,6 +131,50 @@ bool AppRemotingTestDriverEnvironment::GetRemoteHostInfoForApplicationId( ...@@ -127,6 +131,50 @@ bool AppRemotingTestDriverEnvironment::GetRemoteHostInfoForApplicationId(
return remote_host_info->IsReadyForConnection(); return remote_host_info->IsReadyForConnection();
} }
void AppRemotingTestDriverEnvironment::ShowHostAvailability() {
const char kHostAvailabilityFormatString[] = "%-25s%-35s%-10s";
std::vector<std::string>::const_iterator it = application_names_.begin();
LOG(INFO) << base::StringPrintf(kHostAvailabilityFormatString,
"Application Name", "Application ID",
"Status");
while (it != application_names_.end()) {
std::string application_name = *it;
const RemoteApplicationDetails& application_details = GetDetailsFromAppName(
application_name);
RemoteHostInfo remote_host_info;
GetRemoteHostInfoForApplicationId(application_details.application_id,
&remote_host_info);
std::string status;
RemoteHostStatus remote_host_status = remote_host_info.remote_host_status;
if (remote_host_status == kRemoteHostStatusReady) {
status = "Ready :)";
} else if (remote_host_status == kRemoteHostStatusPending) {
status = "Pending :|";
} else {
status = "Unknown :(";
}
LOG(INFO) << base::StringPrintf(
kHostAvailabilityFormatString, application_name.c_str(),
application_details.application_id.c_str(), status.c_str());
++it;
}
}
const RemoteApplicationDetails&
AppRemotingTestDriverEnvironment::GetDetailsFromAppName(
const std::string& application_name) {
DCHECK_GT(application_details_map_.count(application_name), 0UL);
return application_details_map_.at(application_name);
}
void AppRemotingTestDriverEnvironment::SetAccessTokenFetcherForTest( void AppRemotingTestDriverEnvironment::SetAccessTokenFetcherForTest(
AccessTokenFetcher* access_token_fetcher) { AccessTokenFetcher* access_token_fetcher) {
DCHECK(access_token_fetcher); DCHECK(access_token_fetcher);
...@@ -164,8 +212,7 @@ bool AppRemotingTestDriverEnvironment::RetrieveAccessToken( ...@@ -164,8 +212,7 @@ bool AppRemotingTestDriverEnvironment::RetrieveAccessToken(
AccessTokenCallback access_token_callback = AccessTokenCallback access_token_callback =
base::Bind(&AppRemotingTestDriverEnvironment::OnAccessTokenRetrieved, base::Bind(&AppRemotingTestDriverEnvironment::OnAccessTokenRetrieved,
base::Unretained(this), base::Unretained(this), run_loop.QuitClosure());
run_loop.QuitClosure());
// If a unit test has set |test_access_token_fetcher_| then we should use it // If a unit test has set |test_access_token_fetcher_| then we should use it
// below. Note that we do not want to destroy the test object at the end of // below. Note that we do not want to destroy the test object at the end of
...@@ -180,15 +227,13 @@ bool AppRemotingTestDriverEnvironment::RetrieveAccessToken( ...@@ -180,15 +227,13 @@ bool AppRemotingTestDriverEnvironment::RetrieveAccessToken(
if (!auth_code.empty()) { if (!auth_code.empty()) {
// If the user passed in an authcode, then use it to retrieve an // If the user passed in an authcode, then use it to retrieve an
// updated access/refresh token. // updated access/refresh token.
access_token_fetcher->GetAccessTokenFromAuthCode( access_token_fetcher->GetAccessTokenFromAuthCode(auth_code,
auth_code, access_token_callback);
access_token_callback);
} else { } else {
DCHECK(!refresh_token_.empty()); DCHECK(!refresh_token_.empty());
access_token_fetcher->GetAccessTokenFromRefreshToken( access_token_fetcher->GetAccessTokenFromRefreshToken(refresh_token_,
refresh_token_, access_token_callback);
access_token_callback);
} }
run_loop.Run(); run_loop.Run();
...@@ -243,9 +288,7 @@ void AppRemotingTestDriverEnvironment::OnRemoteHostInfoRetrieved( ...@@ -243,9 +288,7 @@ void AppRemotingTestDriverEnvironment::OnRemoteHostInfoRetrieved(
const RemoteHostInfo& retrieved_remote_host_info) { const RemoteHostInfo& retrieved_remote_host_info) {
DCHECK(remote_host_info); DCHECK(remote_host_info);
if (retrieved_remote_host_info.IsReadyForConnection()) { *remote_host_info = retrieved_remote_host_info;
*remote_host_info = retrieved_remote_host_info;
}
done_closure.Run(); done_closure.Run();
} }
......
...@@ -5,9 +5,12 @@ ...@@ -5,9 +5,12 @@
#ifndef REMOTING_TEST_APP_REMOTING_TEST_DRIVER_ENVIRONMENT_H_ #ifndef REMOTING_TEST_APP_REMOTING_TEST_DRIVER_ENVIRONMENT_H_
#define REMOTING_TEST_APP_REMOTING_TEST_DRIVER_ENVIRONMENT_H_ #define REMOTING_TEST_APP_REMOTING_TEST_DRIVER_ENVIRONMENT_H_
#include <map>
#include <string> #include <string>
#include <vector>
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "remoting/test/remote_application_details.h"
#include "remoting/test/remote_host_info_fetcher.h" #include "remoting/test/remote_host_info_fetcher.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -23,9 +26,8 @@ struct RemoteHostInfo; ...@@ -23,9 +26,8 @@ struct RemoteHostInfo;
// access tokens and retrieving remote host connection information. // access tokens and retrieving remote host connection information.
class AppRemotingTestDriverEnvironment : public testing::Environment { class AppRemotingTestDriverEnvironment : public testing::Environment {
public: public:
AppRemotingTestDriverEnvironment( AppRemotingTestDriverEnvironment(const std::string& user_name,
const std::string& user_name, ServiceEnvironment service_environment);
ServiceEnvironment service_environment);
~AppRemotingTestDriverEnvironment() override; ~AppRemotingTestDriverEnvironment() override;
// Returns false if a valid access token cannot be retrieved. // Returns false if a valid access token cannot be retrieved.
...@@ -37,9 +39,16 @@ class AppRemotingTestDriverEnvironment : public testing::Environment { ...@@ -37,9 +39,16 @@ class AppRemotingTestDriverEnvironment : public testing::Environment {
// Synchronously request remote host information for |application_id|. // Synchronously request remote host information for |application_id|.
// Returns true if the request was successful and |remote_host_info| is valid. // Returns true if the request was successful and |remote_host_info| is valid.
bool GetRemoteHostInfoForApplicationId( bool GetRemoteHostInfoForApplicationId(const std::string& application_id,
const std::string& application_id, RemoteHostInfo* remote_host_info);
RemoteHostInfo* remote_host_info);
// Retrieves connection information for all known applications and displays
// their availability to STDOUT.
void ShowHostAvailability();
// Provides the RemoteApplicationDetails for the specified |application_name|.
const RemoteApplicationDetails& GetDetailsFromAppName(
const std::string& application_name);
// Used to set fake/mock objects for AppRemotingTestDriverEnvironment tests. // Used to set fake/mock objects for AppRemotingTestDriverEnvironment tests.
void SetAccessTokenFetcherForTest(AccessTokenFetcher* access_token_fetcher); void SetAccessTokenFetcherForTest(AccessTokenFetcher* access_token_fetcher);
...@@ -59,18 +68,25 @@ class AppRemotingTestDriverEnvironment : public testing::Environment { ...@@ -59,18 +68,25 @@ class AppRemotingTestDriverEnvironment : public testing::Environment {
// Called after the access token fetcher completes. // Called after the access token fetcher completes.
// The tokens will be empty on failure. // The tokens will be empty on failure.
void OnAccessTokenRetrieved( void OnAccessTokenRetrieved(base::Closure done_closure,
base::Closure done_closure, const std::string& access_token,
const std::string& access_token, const std::string& refresh_token);
const std::string& refresh_token);
// Called after the remote host info fetcher completes. // Called after the remote host info fetcher completes.
// |remote_host_info| is not modified on failure. // |remote_host_info| is modified on failure.
void OnRemoteHostInfoRetrieved( void OnRemoteHostInfoRetrieved(
base::Closure done_closure, base::Closure done_closure,
RemoteHostInfo* remote_host_info, RemoteHostInfo* remote_host_info,
const RemoteHostInfo& retrieved_remote_host_info); const RemoteHostInfo& retrieved_remote_host_info);
// Populates |application_names_| with the names of the supported remote
// applications.
void PopulateApplicationNames();
// Populates |application_details_map_| with the RemoteApplicationDetails for
// all supported remote applications.
void PopulateApplicationDetailsMap();
// Used for authenticating with the app remoting service API. // Used for authenticating with the app remoting service API.
std::string access_token_; std::string access_token_;
...@@ -92,6 +108,12 @@ class AppRemotingTestDriverEnvironment : public testing::Environment { ...@@ -92,6 +108,12 @@ class AppRemotingTestDriverEnvironment : public testing::Environment {
// RemoteHostInfoFetcher used by TestDriverEnvironment tests. // RemoteHostInfoFetcher used by TestDriverEnvironment tests.
remoting::test::RemoteHostInfoFetcher* test_remote_host_info_fetcher_; remoting::test::RemoteHostInfoFetcher* test_remote_host_info_fetcher_;
// Contains the names of all supported remote applications.
std::vector<std::string> application_names_;
// Contains RemoteApplicationDetails for all supported remote applications.
std::map<std::string, RemoteApplicationDetails> application_details_map_;
DISALLOW_COPY_AND_ASSIGN(AppRemotingTestDriverEnvironment); DISALLOW_COPY_AND_ASSIGN(AppRemotingTestDriverEnvironment);
}; };
......
// Copyright 2015 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 "remoting/test/app_remoting_test_driver_environment.h"
namespace remoting {
namespace test {
void AppRemotingTestDriverEnvironment::PopulateApplicationNames() {
// The public version of this method is stubbed out as there isn't a publicly
// available test application.
}
void AppRemotingTestDriverEnvironment::PopulateApplicationDetailsMap() {
// The public version of this method is stubbed out as there isn't a publicly
// available test application.
}
} // namespace test
} // namespace remoting
// Copyright 2015 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 REMOTING_TEST_REMOTE_APPLICATION_DETAILS_H_
#define REMOTING_TEST_REMOTE_APPLICATION_DETAILS_H_
#include <string>
namespace remoting {
namespace test {
// Container for application details used for testing.
struct RemoteApplicationDetails {
RemoteApplicationDetails(const std::string& app_id,
const std::string& window_title)
: application_id(app_id), main_window_title(window_title) {}
std::string application_id;
std::string main_window_title;
};
} // namespace test
} // namespace remoting
#endif // REMOTING_TEST_REMOTE_APPLICATION_DETAILS_H_
...@@ -25,9 +25,11 @@ const char kRequestTestOrigin[] = ...@@ -25,9 +25,11 @@ const char kRequestTestOrigin[] =
namespace remoting { namespace remoting {
namespace test { namespace test {
RemoteHostInfoFetcher::RemoteHostInfoFetcher() {} RemoteHostInfoFetcher::RemoteHostInfoFetcher() {
}
RemoteHostInfoFetcher::~RemoteHostInfoFetcher() {} RemoteHostInfoFetcher::~RemoteHostInfoFetcher() {
}
bool RemoteHostInfoFetcher::RetrieveRemoteHostInfo( bool RemoteHostInfoFetcher::RetrieveRemoteHostInfo(
const std::string& application_id, const std::string& application_id,
...@@ -62,14 +64,13 @@ bool RemoteHostInfoFetcher::RetrieveRemoteHostInfo( ...@@ -62,14 +64,13 @@ bool RemoteHostInfoFetcher::RetrieveRemoteHostInfo(
remote_host_info_callback_ = callback; remote_host_info_callback_ = callback;
scoped_refptr<remoting::URLRequestContextGetter> request_context_getter; request_context_getter_ = new remoting::URLRequestContextGetter(
request_context_getter = new remoting::URLRequestContextGetter(
base::ThreadTaskRunnerHandle::Get(), // network_runner base::ThreadTaskRunnerHandle::Get(), // network_runner
base::ThreadTaskRunnerHandle::Get()); // file_runner base::ThreadTaskRunnerHandle::Get()); // file_runner
request_.reset( request_.reset(
net::URLFetcher::Create(GURL(service_url), net::URLFetcher::POST, this)); net::URLFetcher::Create(GURL(service_url), net::URLFetcher::POST, this));
request_->SetRequestContext(request_context_getter.get()); request_->SetRequestContext(request_context_getter_.get());
request_->AddExtraRequestHeader("Authorization: OAuth " + access_token); request_->AddExtraRequestHeader("Authorization: OAuth " + access_token);
request_->AddExtraRequestHeader(kRequestTestOrigin); request_->AddExtraRequestHeader(kRequestTestOrigin);
request_->SetUploadData("application/json; charset=UTF-8", "{}"); request_->SetUploadData("application/json; charset=UTF-8", "{}");
......
...@@ -36,9 +36,9 @@ const char kTestServiceEnvironmentUrlFormat[] = ...@@ -36,9 +36,9 @@ const char kTestServiceEnvironmentUrlFormat[] =
// Note: When adding new environments, add them before kUnknownEnvironment as // Note: When adding new environments, add them before kUnknownEnvironment as
// the last entry is used for bounds checking. // the last entry is used for bounds checking.
enum ServiceEnvironment { enum ServiceEnvironment {
kDeveloperEnvironment, kDeveloperEnvironment,
kTestingEnvironment, kTestingEnvironment,
kUnknownEnvironment kUnknownEnvironment
}; };
// Supplied by the client for each remote host info request and returns a valid, // Supplied by the client for each remote host info request and returns a valid,
...@@ -58,11 +58,10 @@ class RemoteHostInfoFetcher : public net::URLFetcherDelegate { ...@@ -58,11 +58,10 @@ class RemoteHostInfoFetcher : public net::URLFetcherDelegate {
// Makes a service call to retrieve the details for a remote host. The // Makes a service call to retrieve the details for a remote host. The
// callback will be called once the HTTP request has completed. // callback will be called once the HTTP request has completed.
virtual bool RetrieveRemoteHostInfo( virtual bool RetrieveRemoteHostInfo(const std::string& application_id,
const std::string& application_id, const std::string& access_token,
const std::string& access_token, ServiceEnvironment service_environment,
ServiceEnvironment service_environment, const RemoteHostInfoCallback& callback);
const RemoteHostInfoCallback& callback);
private: private:
// net::URLFetcherDelegate interface. // net::URLFetcherDelegate interface.
...@@ -71,6 +70,9 @@ class RemoteHostInfoFetcher : public net::URLFetcherDelegate { ...@@ -71,6 +70,9 @@ class RemoteHostInfoFetcher : public net::URLFetcherDelegate {
// Holds the URLFetcher for the RemoteHostInfo request. // Holds the URLFetcher for the RemoteHostInfo request.
scoped_ptr<net::URLFetcher> request_; scoped_ptr<net::URLFetcher> request_;
// Provides application-specific context for the network request.
scoped_refptr<remoting::URLRequestContextGetter> request_context_getter_;
// Caller-supplied callback used to return remote host info on success. // Caller-supplied callback used to return remote host info on success.
RemoteHostInfoCallback remote_host_info_callback_; RemoteHostInfoCallback remote_host_info_callback_;
......
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
namespace { namespace {
const char kAppRemotingCapabilities[] =
"rateLimitResizeRequests desktopShape sendInitialResolution googleDrive";
const char kXmppHostName[] = "talk.google.com"; const char kXmppHostName[] = "talk.google.com";
const int kXmppPortNumber = 5222; const int kXmppPortNumber = 5222;
...@@ -160,8 +163,7 @@ void TestChromotingClient::StartConnection( ...@@ -160,8 +163,7 @@ void TestChromotingClient::StartConnection(
chromoting_client_.reset(new ChromotingClient(client_context_.get(), chromoting_client_.reset(new ChromotingClient(client_context_.get(),
this, // client_user_interface. this, // client_user_interface.
video_renderer_.get(), video_renderer_.get(),
nullptr // audio_player nullptr)); // audio_player
));
if (test_connection_to_host_) { if (test_connection_to_host_) {
chromoting_client_->SetConnectionToHostForTests( chromoting_client_->SetConnectionToHostForTests(
...@@ -212,8 +214,7 @@ void TestChromotingClient::StartConnection( ...@@ -212,8 +214,7 @@ void TestChromotingClient::StartConnection(
chromoting_client_->Start(signal_strategy_.get(), authenticator.Pass(), chromoting_client_->Start(signal_strategy_.get(), authenticator.Pass(),
transport_factory.Pass(), remote_host_info.host_jid, transport_factory.Pass(), remote_host_info.host_jid,
std::string() // capabilities kAppRemotingCapabilities);
);
} }
void TestChromotingClient::EndConnection() { void TestChromotingClient::EndConnection() {
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "remoting/client/chromoting_client.h"
#include "remoting/client/client_user_interface.h" #include "remoting/client/client_user_interface.h"
#include "remoting/protocol/clipboard_filter.h" #include "remoting/protocol/clipboard_filter.h"
#include "remoting/protocol/cursor_shape_stub.h" #include "remoting/protocol/cursor_shape_stub.h"
...@@ -17,13 +18,17 @@ ...@@ -17,13 +18,17 @@
#include "remoting/test/remote_host_info.h" #include "remoting/test/remote_host_info.h"
namespace remoting { namespace remoting {
class ChromotingClient;
class ClientContext; class ClientContext;
class XmppSignalStrategy; class XmppSignalStrategy;
class VideoRenderer; class VideoRenderer;
namespace protocol {
class ClipboardStub;
class HostStub;
class InputStub;
} }
namespace remoting {
namespace test { namespace test {
// Manages a chromoting connection to a remote host. Destroying a // Manages a chromoting connection to a remote host. Destroying a
...@@ -46,6 +51,13 @@ class TestChromotingClient : public ClientUserInterface, ...@@ -46,6 +51,13 @@ class TestChromotingClient : public ClientUserInterface,
// Ends the current remote connection and updates the connection state. // Ends the current remote connection and updates the connection state.
void EndConnection(); void EndConnection();
// Stubs used to send messages to the remote host.
protocol::ClipboardStub* clipboard_forwarder() {
return chromoting_client_->clipboard_forwarder();
}
protocol::HostStub* host_stub() { return chromoting_client_->host_stub(); }
protocol::InputStub* input_stub() { return chromoting_client_->input_stub(); }
// Registers an observer which will be notfied when remote connection events // Registers an observer which will be notfied when remote connection events
// occur. Registered Observers must not tear-down this object on receipt of // occur. Registered Observers must not tear-down this object on receipt of
// these callbacks. The callbacks should be used for informational purposes. // these callbacks. The callbacks should be used for informational purposes.
......
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