Chromium Code Reviews| Index: remoting/host/client_session_unittest.cc |
| diff --git a/remoting/host/client_session_unittest.cc b/remoting/host/client_session_unittest.cc |
| index f28050a9a43fab6da148ac0752f2736c928c3826..c663b6bf02feeaf199b22f789228fa9c9915f497 100644 |
| --- a/remoting/host/client_session_unittest.cc |
| +++ b/remoting/host/client_session_unittest.cc |
| @@ -3,12 +3,14 @@ |
| // found in the LICENSE file. |
| #include "base/message_loop/message_loop.h" |
| +#include "base/strings/string_util.h" |
| #include "base/test/test_simple_task_runner.h" |
| #include "remoting/base/auto_thread_task_runner.h" |
| #include "remoting/base/constants.h" |
| #include "remoting/host/audio_capturer.h" |
| #include "remoting/host/client_session.h" |
| #include "remoting/host/desktop_environment.h" |
| +#include "remoting/host/extension.h" |
| #include "remoting/host/host_mock_objects.h" |
| #include "remoting/host/screen_capturer_fake.h" |
| #include "remoting/protocol/protocol_mock_objects.h" |
| @@ -34,6 +36,7 @@ using testing::AtMost; |
| using testing::DeleteArg; |
| using testing::DoAll; |
| using testing::Expectation; |
| +using testing::Invoke; |
| using testing::Return; |
| using testing::ReturnRef; |
| using testing::Sequence; |
| @@ -42,6 +45,8 @@ using testing::StrictMock; |
| namespace { |
| +const char kDefaultTestCapability[] = "default"; |
| + |
| ACTION_P2(InjectClipboardEvent, connection, event) { |
| connection->clipboard_stub()->InjectClipboardEvent(event); |
| } |
| @@ -67,6 +72,56 @@ ACTION_P2(DeliverClientMessage, client_session, message) { |
| client_session->DeliverClientMessage(message); |
| } |
| +// Matches a |protocol::Capabilities| argument against a list of capabilities |
| +// formatted as a space-separated string. |
| +MATCHER_P(EqCapabilities, expected_capabilities, "") { |
| + if (!arg.has_capabilities()) |
| + return false; |
| + |
| + std::vector<std::string> words_args; |
| + std::vector<std::string> words_expected; |
| + Tokenize(arg.capabilities(), " ", &words_args); |
| + Tokenize(expected_capabilities, " ", &words_expected); |
| + std::sort(words_args.begin(), words_args.end()); |
| + std::sort(words_expected.begin(), words_expected.end()); |
| + return words_args == words_expected; |
| +} |
| + |
| +// |Extension| implementation that can handle an extension message type and |
| +// provide capabilities. |
| +class FakeExtension : public Extension { |
| + public: |
| + FakeExtension(const std::string& message_type, |
| + const std::string& capabilities); |
| + virtual ~FakeExtension(); |
| + |
| + virtual std::string GetCapabilities() OVERRIDE; |
| + virtual scoped_ptr<ExtensionSession> CreateExtensionSession( |
| + ClientSession* client_session) OVERRIDE; |
| + |
| + bool message_handled() { |
| + return message_handled_; |
| + } |
| + |
| + private: |
| + class FakeExtensionSession : public ExtensionSession { |
| + public: |
| + FakeExtensionSession(FakeExtension* extension); |
| + virtual ~FakeExtensionSession(); |
| + |
| + virtual bool OnExtensionMessage( |
| + ClientSession* client_session, |
| + const protocol::ExtensionMessage& message) OVERRIDE; |
| + |
| + private: |
| + FakeExtension* extension_; |
| + }; |
| + |
| + std::string message_type_; |
| + std::string capabilities_; |
| + bool message_handled_; |
| +}; |
| + |
| } |
| class ClientSessionTest : public testing::Test { |
| @@ -128,9 +183,46 @@ class ClientSessionTest : public testing::Test { |
| // ClientSession owns |connection_| but tests need it to inject fake events. |
| MockConnectionToClient* connection_; |
| + ExtensionList extensions_; |
| + |
| scoped_ptr<MockDesktopEnvironmentFactory> desktop_environment_factory_; |
| }; |
| +FakeExtension::FakeExtension(const std::string& message_type, |
| + const std::string& capabilities) |
| + : message_type_(message_type), |
| + capabilities_(capabilities), |
| + message_handled_(false) { |
| +} |
| + |
| +FakeExtension::~FakeExtension() {} |
| + |
| +std::string FakeExtension::GetCapabilities() { |
| + return capabilities_; |
| +} |
| + |
| +scoped_ptr<ExtensionSession> FakeExtension::CreateExtensionSession( |
| + ClientSession* client_session) { |
| + return scoped_ptr<ExtensionSession>(new FakeExtensionSession(this)); |
| +} |
| + |
| +FakeExtension::FakeExtensionSession::FakeExtensionSession( |
| + FakeExtension* extension) |
| + : extension_(extension) { |
| +} |
| + |
| +FakeExtension::FakeExtensionSession::~FakeExtensionSession() {} |
| + |
| +bool FakeExtension::FakeExtensionSession::OnExtensionMessage( |
| + ClientSession* client_session, |
| + const protocol::ExtensionMessage& message) { |
| + if (message.type() == extension_->message_type_) { |
| + extension_->message_handled_ = true; |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| void ClientSessionTest::SetUp() { |
| // Arrange to run |message_loop_| until no components depend on it. |
| scoped_refptr<AutoThreadTaskRunner> ui_task_runner = new AutoThreadTaskRunner( |
| @@ -179,7 +271,13 @@ void ClientSessionTest::SetUp() { |
| connection.PassAs<protocol::ConnectionToClient>(), |
| desktop_environment_factory_.get(), |
| base::TimeDelta(), |
| - NULL)); |
| + NULL, |
| + &extensions_)); |
| + |
| + // By default, client will report the same capabilities as the host. |
| + EXPECT_CALL(client_stub_, SetCapabilities(_)) |
| + .Times(AtMost(1)) |
| + .WillOnce(Invoke(client_session_.get(), &ClientSession::SetCapabilities)); |
| } |
| void ClientSessionTest::TearDown() { |
| @@ -211,7 +309,8 @@ DesktopEnvironment* ClientSessionTest::CreateDesktopEnvironment() { |
| EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr()) |
| .WillOnce(Invoke(this, &ClientSessionTest::CreateVideoCapturer)); |
| EXPECT_CALL(*desktop_environment, GetCapabilities()) |
| - .Times(AtMost(1)); |
| + .Times(AtMost(1)) |
| + .WillOnce(Return(kDefaultTestCapability)); |
| EXPECT_CALL(*desktop_environment, SetCapabilities(_)) |
| .Times(AtMost(1)); |
| @@ -599,4 +698,90 @@ TEST_F(ClientSessionTest, EnableGnubbyAuth) { |
| message_loop_.Run(); |
| } |
| +// Verifies that messages can be handled by extensions. |
| +TEST_F(ClientSessionTest, ExtensionMessages_MessageHandled) { |
| + FakeExtension extension1("ext1", "cap1"); |
| + FakeExtension extension2("ext2", "cap2"); |
| + FakeExtension extension3("ext3", "cap3"); |
| + extensions_.push_back(&extension1); |
| + extensions_.push_back(&extension2); |
| + extensions_.push_back(&extension3); |
| + |
| + protocol::ExtensionMessage message; |
| + message.set_type("ext2"); |
| + message.set_data("test"); |
| + |
| + Expectation authenticated = |
| + EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)) |
| + .WillOnce(Return(true)); |
| + EXPECT_CALL(*input_injector_, StartPtr(_)).After(authenticated); |
| + EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_)) |
| + .After(authenticated) |
| + .WillOnce(DoAll( |
| + DeliverClientMessage(client_session_.get(), message), |
| + InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession), |
| + InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession))); |
|
Wez
2014/05/28 01:05:59
This chunk of work is unrelated to the test, aside
dcaiafa
2014/05/28 22:44:58
Done.
|
| + |
| + ConnectClientSession(); |
| + message_loop_.Run(); |
| + |
| + EXPECT_FALSE(extension1.message_handled()); |
| + EXPECT_TRUE(extension2.message_handled()); |
| + EXPECT_FALSE(extension3.message_handled()); |
| +} |
| + |
| +// Verifies that extension messages not handled by extensions don't result in a |
| +// crash. |
| +TEST_F(ClientSessionTest, ExtensionMessages_MessageNotHandled) { |
| + FakeExtension extension1("ext1", "cap1"); |
| + extensions_.push_back(&extension1); |
| + |
| + protocol::ExtensionMessage message; |
| + message.set_type("extX"); |
| + message.set_data("test"); |
| + |
| + Expectation authenticated = |
| + EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)) |
| + .WillOnce(Return(true)); |
| + EXPECT_CALL(*input_injector_, StartPtr(_)).After(authenticated); |
| + EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_)) |
| + .After(authenticated) |
| + .WillOnce(DoAll( |
| + DeliverClientMessage(client_session_.get(), message), |
| + InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession), |
| + InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession))); |
| + |
| + ConnectClientSession(); |
| + message_loop_.Run(); |
| + |
| + EXPECT_FALSE(extension1.message_handled()); |
| +} |
| + |
| + // Verifies that host factors in extension capabilties when reporting |
|
Wez
2014/05/28 01:05:59
typo:
dcaiafa
2014/05/28 22:44:58
Done.
|
| + // capabilities to the client. |
|
Wez
2014/05/28 01:05:59
These lines look to be wrongly indented?
dcaiafa
2014/05/28 22:44:58
Done.
|
| +TEST_F(ClientSessionTest, ExtensionMessages_Capabilities) { |
| + FakeExtension extension1("ext1", ""); |
| + FakeExtension extension2("ext2", "capX capZ"); |
| + FakeExtension extension3("ext3", "capY"); |
| + extensions_.push_back(&extension1); |
| + extensions_.push_back(&extension2); |
| + extensions_.push_back(&extension3); |
| + |
| + Expectation authenticated = |
| + EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)) |
| + .WillOnce(Return(true)); |
| + EXPECT_CALL(*input_injector_, StartPtr(_)).After(authenticated); |
| + EXPECT_CALL(client_stub_, |
| + SetCapabilities(EqCapabilities("capX capY capZ default"))) |
| + .After(authenticated); |
| + EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_)) |
| + .After(authenticated) |
| + .WillOnce(DoAll( |
| + InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession), |
| + InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession))); |
| + |
| + ConnectClientSession(); |
| + message_loop_.Run(); |
| +} |
| + |
| } // namespace remoting |