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 |