blob: a8b979798489cce66458380ae5e181538fbbf65f [file] [log] [blame]
[email protected]b5a6afe2012-01-07 05:48:201// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]1bc9c7c2011-12-14 00:13:392// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]6c44b532012-02-24 21:57:445#include "remoting/protocol/jingle_session.h"
[email protected]1bc9c7c2011-12-14 00:13:396
7#include "base/bind.h"
8#include "base/message_loop.h"
9#include "base/time.h"
10#include "base/test/test_timeouts.h"
[email protected]ad48b7f2012-02-21 21:20:0211#include "net/socket/socket.h"
12#include "net/socket/stream_socket.h"
[email protected]1bc9c7c2011-12-14 00:13:3913#include "remoting/base/constants.h"
14#include "remoting/protocol/authenticator.h"
15#include "remoting/protocol/channel_authenticator.h"
16#include "remoting/protocol/connection_tester.h"
17#include "remoting/protocol/fake_authenticator.h"
[email protected]6c44b532012-02-24 21:57:4418#include "remoting/protocol/jingle_session_manager.h"
[email protected]ad48b7f2012-02-21 21:20:0219#include "remoting/protocol/libjingle_transport_factory.h"
[email protected]1bc9c7c2011-12-14 00:13:3920#include "remoting/jingle_glue/jingle_thread.h"
21#include "remoting/jingle_glue/fake_signal_strategy.h"
22#include "testing/gmock/include/gmock/gmock.h"
23#include "testing/gtest/include/gtest/gtest.h"
24
25using testing::_;
26using testing::AtMost;
27using testing::DeleteArg;
28using testing::DoAll;
29using testing::InSequence;
30using testing::Invoke;
31using testing::InvokeWithoutArgs;
32using testing::Return;
33using testing::SaveArg;
34using testing::SetArgumentPointee;
35using testing::WithArg;
36
37namespace remoting {
38namespace protocol {
39
40namespace {
41
42const char kHostJid[] = "[email protected]/123";
43const char kClientJid[] = "[email protected]/321";
44
[email protected]ad48b7f2012-02-21 21:20:0245// Send 100 messages 1024 bytes each. UDP messages are sent with 10ms delay
46// between messages (about 1 second for 100 messages).
47const int kMessageSize = 1024;
48const int kMessages = 100;
49const char kChannelName[] = "test_channel";
50
51void QuitCurrentThread() {
52 MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
53}
54
55ACTION_P(QuitThreadOnCounter, counter) {
56 --(*counter);
57 EXPECT_GE(*counter, 0);
58 if (*counter == 0)
59 QuitCurrentThread();
60}
61
[email protected]1bc9c7c2011-12-14 00:13:3962class MockSessionManagerListener : public SessionManager::Listener {
63 public:
[email protected]08128a312012-01-03 21:02:3964 MOCK_METHOD0(OnSessionManagerReady, void());
[email protected]1bc9c7c2011-12-14 00:13:3965 MOCK_METHOD2(OnIncomingSession,
66 void(Session*,
67 SessionManager::IncomingSessionResponse*));
68};
69
70class MockSessionCallback {
71 public:
72 MOCK_METHOD1(OnStateChange, void(Session::State));
73};
74
[email protected]ad48b7f2012-02-21 21:20:0275class MockStreamChannelCallback {
76 public:
77 MOCK_METHOD1(OnDone, void(net::StreamSocket* socket));
78};
79
[email protected]1bc9c7c2011-12-14 00:13:3980} // namespace
81
[email protected]6c44b532012-02-24 21:57:4482class JingleSessionTest : public testing::Test {
[email protected]1bc9c7c2011-12-14 00:13:3983 public:
[email protected]836c8972012-03-01 18:35:0884 JingleSessionTest() {
85 talk_base::ThreadManager::Instance()->WrapCurrentThread();
86 message_loop_.reset(
87 new JingleThreadMessageLoop(talk_base::Thread::Current()));
[email protected]1bc9c7c2011-12-14 00:13:3988 }
89
90 // Helper method that handles OnIncomingSession().
91 void SetHostSession(Session* session) {
92 DCHECK(session);
93 host_session_.reset(session);
94 host_session_->SetStateChangeCallback(
95 base::Bind(&MockSessionCallback::OnStateChange,
96 base::Unretained(&host_connection_callback_)));
97
98 session->set_config(SessionConfig::GetDefault());
99 }
100
[email protected]ad48b7f2012-02-21 21:20:02101 void OnClientChannelCreated(scoped_ptr<net::StreamSocket> socket) {
102 client_channel_callback_.OnDone(socket.get());
103 client_socket_ = socket.Pass();
104 }
105
106 void OnHostChannelCreated(scoped_ptr<net::StreamSocket> socket) {
107 host_channel_callback_.OnDone(socket.get());
108 host_socket_ = socket.Pass();
109 }
110
[email protected]1bc9c7c2011-12-14 00:13:39111 protected:
112 virtual void SetUp() {
113 }
114
115 virtual void TearDown() {
116 CloseSessions();
117 CloseSessionManager();
[email protected]836c8972012-03-01 18:35:08118 message_loop_->RunAllPending();
[email protected]1bc9c7c2011-12-14 00:13:39119 }
120
121 void CloseSessions() {
[email protected]ad48b7f2012-02-21 21:20:02122 host_socket_.reset();
[email protected]1bc9c7c2011-12-14 00:13:39123 host_session_.reset();
[email protected]ad48b7f2012-02-21 21:20:02124 client_socket_.reset();
[email protected]1bc9c7c2011-12-14 00:13:39125 client_session_.reset();
126 }
127
128 void CreateSessionManagers(int auth_round_trips,
129 FakeAuthenticator::Action auth_action) {
130 host_signal_strategy_.reset(new FakeSignalStrategy(kHostJid));
131 client_signal_strategy_.reset(new FakeSignalStrategy(kClientJid));
132 FakeSignalStrategy::Connect(host_signal_strategy_.get(),
133 client_signal_strategy_.get());
134
[email protected]08128a312012-01-03 21:02:39135 EXPECT_CALL(host_server_listener_, OnSessionManagerReady())
[email protected]1bc9c7c2011-12-14 00:13:39136 .Times(1);
[email protected]6c44b532012-02-24 21:57:44137 host_server_.reset(new JingleSessionManager(
[email protected]ad48b7f2012-02-21 21:20:02138 scoped_ptr<TransportFactory>(new LibjingleTransportFactory())));
[email protected]d286b6732012-01-13 21:18:32139 host_server_->Init(host_signal_strategy_.get(), &host_server_listener_,
140 NetworkSettings(false));
[email protected]1bc9c7c2011-12-14 00:13:39141
[email protected]b5a6afe2012-01-07 05:48:20142 scoped_ptr<AuthenticatorFactory> factory(
[email protected]1bc9c7c2011-12-14 00:13:39143 new FakeHostAuthenticatorFactory(auth_round_trips, auth_action, true));
[email protected]b5a6afe2012-01-07 05:48:20144 host_server_->set_authenticator_factory(factory.Pass());
[email protected]1bc9c7c2011-12-14 00:13:39145
[email protected]08128a312012-01-03 21:02:39146 EXPECT_CALL(client_server_listener_, OnSessionManagerReady())
[email protected]1bc9c7c2011-12-14 00:13:39147 .Times(1);
[email protected]6c44b532012-02-24 21:57:44148 client_server_.reset(new JingleSessionManager(
[email protected]ad48b7f2012-02-21 21:20:02149 scoped_ptr<TransportFactory>(new LibjingleTransportFactory())));
[email protected]d286b6732012-01-13 21:18:32150 client_server_->Init(client_signal_strategy_.get(),
151 &client_server_listener_, NetworkSettings());
[email protected]1bc9c7c2011-12-14 00:13:39152 }
153
154 void CloseSessionManager() {
155 if (host_server_.get()) {
156 host_server_->Close();
157 host_server_.reset();
158 }
159 if (client_server_.get()) {
160 client_server_->Close();
161 client_server_.reset();
162 }
163 host_signal_strategy_.reset();
164 client_signal_strategy_.reset();
165 }
166
167 void InitiateConnection(int auth_round_trips,
168 FakeAuthenticator::Action auth_action,
169 bool expect_fail) {
170 EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _))
171 .WillOnce(DoAll(
[email protected]6c44b532012-02-24 21:57:44172 WithArg<0>(Invoke(this, &JingleSessionTest::SetHostSession)),
[email protected]1bc9c7c2011-12-14 00:13:39173 SetArgumentPointee<1>(protocol::SessionManager::ACCEPT)));
174
175 {
176 InSequence dummy;
177
178 EXPECT_CALL(host_connection_callback_,
179 OnStateChange(Session::CONNECTED))
180 .Times(AtMost(1));
181 if (expect_fail) {
182 EXPECT_CALL(host_connection_callback_,
183 OnStateChange(Session::FAILED))
184 .Times(1);
185 } else {
186 EXPECT_CALL(host_connection_callback_,
187 OnStateChange(Session::AUTHENTICATED))
188 .Times(1);
189 // Expect that the connection will be closed eventually.
190 EXPECT_CALL(host_connection_callback_,
191 OnStateChange(Session::CLOSED))
192 .Times(AtMost(1));
193 }
194 }
195
196 {
197 InSequence dummy;
198
199 EXPECT_CALL(client_connection_callback_,
200 OnStateChange(Session::CONNECTING))
201 .Times(1);
202 EXPECT_CALL(client_connection_callback_,
203 OnStateChange(Session::CONNECTED))
204 .Times(AtMost(1));
205 if (expect_fail) {
206 EXPECT_CALL(client_connection_callback_,
207 OnStateChange(Session::FAILED))
208 .Times(1);
209 } else {
210 EXPECT_CALL(client_connection_callback_,
211 OnStateChange(Session::AUTHENTICATED))
212 .Times(1);
213 // Expect that the connection will be closed eventually.
214 EXPECT_CALL(client_connection_callback_,
215 OnStateChange(Session::CLOSED))
216 .Times(AtMost(1));
217 }
218 }
219
[email protected]5bf52312012-01-20 04:10:52220 scoped_ptr<Authenticator> authenticator(new FakeAuthenticator(
221 FakeAuthenticator::CLIENT, auth_round_trips, auth_action, true));
[email protected]1bc9c7c2011-12-14 00:13:39222
[email protected]5bf52312012-01-20 04:10:52223 client_session_ = client_server_->Connect(
224 kHostJid, authenticator.Pass(),
[email protected]1bc9c7c2011-12-14 00:13:39225 CandidateSessionConfig::CreateDefault(),
226 base::Bind(&MockSessionCallback::OnStateChange,
[email protected]5bf52312012-01-20 04:10:52227 base::Unretained(&client_connection_callback_)));
[email protected]1bc9c7c2011-12-14 00:13:39228
[email protected]836c8972012-03-01 18:35:08229 message_loop_->RunAllPending();
[email protected]1bc9c7c2011-12-14 00:13:39230 }
231
[email protected]284d3842012-02-24 04:27:45232 void CreateChannel(bool expect_fail) {
[email protected]ad48b7f2012-02-21 21:20:02233 client_session_->CreateStreamChannel(kChannelName, base::Bind(
[email protected]6c44b532012-02-24 21:57:44234 &JingleSessionTest::OnClientChannelCreated, base::Unretained(this)));
[email protected]ad48b7f2012-02-21 21:20:02235 host_session_->CreateStreamChannel(kChannelName, base::Bind(
[email protected]6c44b532012-02-24 21:57:44236 &JingleSessionTest::OnHostChannelCreated, base::Unretained(this)));
[email protected]ad48b7f2012-02-21 21:20:02237
238 int counter = 2;
239 EXPECT_CALL(client_channel_callback_, OnDone(_))
240 .WillOnce(QuitThreadOnCounter(&counter));
241 EXPECT_CALL(host_channel_callback_, OnDone(_))
242 .WillOnce(QuitThreadOnCounter(&counter));
[email protected]836c8972012-03-01 18:35:08243 message_loop_->Run();
[email protected]284d3842012-02-24 04:27:45244
245 if (expect_fail) {
246 // At least one socket should fail to connect.
247 EXPECT_TRUE((!client_socket_.get()) || (!host_socket_.get()));
248 } else {
249 EXPECT_TRUE(client_socket_.get());
250 EXPECT_TRUE(host_socket_.get());
251 }
[email protected]ad48b7f2012-02-21 21:20:02252 }
253
[email protected]836c8972012-03-01 18:35:08254 scoped_ptr<JingleThreadMessageLoop> message_loop_;
[email protected]1bc9c7c2011-12-14 00:13:39255
256 scoped_ptr<FakeSignalStrategy> host_signal_strategy_;
257 scoped_ptr<FakeSignalStrategy> client_signal_strategy_;
258
[email protected]6c44b532012-02-24 21:57:44259 scoped_ptr<JingleSessionManager> host_server_;
[email protected]1bc9c7c2011-12-14 00:13:39260 MockSessionManagerListener host_server_listener_;
[email protected]6c44b532012-02-24 21:57:44261 scoped_ptr<JingleSessionManager> client_server_;
[email protected]1bc9c7c2011-12-14 00:13:39262 MockSessionManagerListener client_server_listener_;
263
264 scoped_ptr<Session> host_session_;
265 MockSessionCallback host_connection_callback_;
266 scoped_ptr<Session> client_session_;
267 MockSessionCallback client_connection_callback_;
[email protected]ad48b7f2012-02-21 21:20:02268
269 MockStreamChannelCallback client_channel_callback_;
270 MockStreamChannelCallback host_channel_callback_;
271
272 scoped_ptr<net::StreamSocket> client_socket_;
273 scoped_ptr<net::StreamSocket> host_socket_;
[email protected]1bc9c7c2011-12-14 00:13:39274};
275
276
277// Verify that we can create and destroy session managers without a
278// connection.
[email protected]6c44b532012-02-24 21:57:44279TEST_F(JingleSessionTest, CreateAndDestoy) {
[email protected]1bc9c7c2011-12-14 00:13:39280 CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
281}
282
283// Verify that an incoming session can be rejected, and that the
284// status of the connection is set to FAILED in this case.
[email protected]6c44b532012-02-24 21:57:44285TEST_F(JingleSessionTest, RejectConnection) {
[email protected]1bc9c7c2011-12-14 00:13:39286 CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
287
288 // Reject incoming session.
289 EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _))
290 .WillOnce(SetArgumentPointee<1>(protocol::SessionManager::DECLINE));
291
292 {
293 InSequence dummy;
294
295 EXPECT_CALL(client_connection_callback_,
296 OnStateChange(Session::CONNECTING))
297 .Times(1);
298 EXPECT_CALL(client_connection_callback_,
299 OnStateChange(Session::FAILED))
300 .Times(1);
301 }
302
[email protected]5bf52312012-01-20 04:10:52303 scoped_ptr<Authenticator> authenticator(new FakeAuthenticator(
304 FakeAuthenticator::CLIENT, 1, FakeAuthenticator::ACCEPT, true));
305 client_session_ = client_server_->Connect(
306 kHostJid, authenticator.Pass(), CandidateSessionConfig::CreateDefault(),
[email protected]1bc9c7c2011-12-14 00:13:39307 base::Bind(&MockSessionCallback::OnStateChange,
[email protected]5bf52312012-01-20 04:10:52308 base::Unretained(&client_connection_callback_)));
[email protected]1bc9c7c2011-12-14 00:13:39309
[email protected]836c8972012-03-01 18:35:08310 message_loop_->RunAllPending();
[email protected]1bc9c7c2011-12-14 00:13:39311}
312
313// Verify that we can connect two endpoints with single-step authentication.
[email protected]6c44b532012-02-24 21:57:44314TEST_F(JingleSessionTest, Connect) {
[email protected]1bc9c7c2011-12-14 00:13:39315 CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
316 InitiateConnection(1, FakeAuthenticator::ACCEPT, false);
[email protected]a05c0d82a2012-02-29 01:19:25317
318 // Verify that the client specified correct initiator value.
319 ASSERT_GT(host_signal_strategy_->received_messages().size(), 0U);
320 const buzz::XmlElement* initiate_xml =
321 host_signal_strategy_->received_messages().front();
322 const buzz::XmlElement* jingle_element =
323 initiate_xml->FirstNamed(buzz::QName(kJingleNamespace, "jingle"));
324 ASSERT_TRUE(jingle_element);
325 ASSERT_EQ(kClientJid,
326 jingle_element->Attr(buzz::QName("", "initiator")));
[email protected]1bc9c7c2011-12-14 00:13:39327}
328
329// Verify that we can connect two endpoints with multi-step authentication.
[email protected]6c44b532012-02-24 21:57:44330TEST_F(JingleSessionTest, ConnectWithMultistep) {
[email protected]1bc9c7c2011-12-14 00:13:39331 CreateSessionManagers(3, FakeAuthenticator::ACCEPT);
332 InitiateConnection(3, FakeAuthenticator::ACCEPT, false);
333}
334
335// Verify that connection is terminated when single-step auth fails.
[email protected]6c44b532012-02-24 21:57:44336TEST_F(JingleSessionTest, ConnectWithBadAuth) {
[email protected]1bc9c7c2011-12-14 00:13:39337 CreateSessionManagers(1, FakeAuthenticator::REJECT);
338 InitiateConnection(1, FakeAuthenticator::ACCEPT, true);
339}
340
341// Verify that connection is terminated when multi-step auth fails.
[email protected]6c44b532012-02-24 21:57:44342TEST_F(JingleSessionTest, ConnectWithBadMultistepAuth) {
[email protected]1bc9c7c2011-12-14 00:13:39343 CreateSessionManagers(3, FakeAuthenticator::REJECT);
344 InitiateConnection(3, FakeAuthenticator::ACCEPT, true);
345}
346
[email protected]284d3842012-02-24 04:27:45347// Verify that data can be sent over stream channel.
[email protected]6c44b532012-02-24 21:57:44348TEST_F(JingleSessionTest, TestStreamChannel) {
[email protected]ad48b7f2012-02-21 21:20:02349 CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
350 ASSERT_NO_FATAL_FAILURE(
351 InitiateConnection(1, FakeAuthenticator::ACCEPT, false));
352
[email protected]284d3842012-02-24 04:27:45353 ASSERT_NO_FATAL_FAILURE(CreateChannel(false));
[email protected]ad48b7f2012-02-21 21:20:02354
355 StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
356 kMessageSize, kMessages);
357 tester.Start();
[email protected]836c8972012-03-01 18:35:08358 message_loop_->Run();
[email protected]ad48b7f2012-02-21 21:20:02359 tester.CheckResults();
360}
361
362// Verify that we can connect channels with multistep auth.
[email protected]6c44b532012-02-24 21:57:44363TEST_F(JingleSessionTest, TestMultistepAuthStreamChannel) {
[email protected]ad48b7f2012-02-21 21:20:02364 CreateSessionManagers(3, FakeAuthenticator::ACCEPT);
365 ASSERT_NO_FATAL_FAILURE(
366 InitiateConnection(3, FakeAuthenticator::ACCEPT, false));
367
[email protected]284d3842012-02-24 04:27:45368 ASSERT_NO_FATAL_FAILURE(CreateChannel(false));
[email protected]ad48b7f2012-02-21 21:20:02369
370 StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
371 kMessageSize, kMessages);
372 tester.Start();
[email protected]836c8972012-03-01 18:35:08373 message_loop_->Run();
[email protected]ad48b7f2012-02-21 21:20:02374 tester.CheckResults();
375}
376
[email protected]284d3842012-02-24 04:27:45377// Verify that we shutdown properly when channel authentication fails.
[email protected]6c44b532012-02-24 21:57:44378TEST_F(JingleSessionTest, TestFailedChannelAuth) {
[email protected]284d3842012-02-24 04:27:45379 CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
380 ASSERT_NO_FATAL_FAILURE(
381 InitiateConnection(1, FakeAuthenticator::REJECT_CHANNEL, false));
382
383 ASSERT_NO_FATAL_FAILURE(CreateChannel(true));
384}
385
[email protected]1bc9c7c2011-12-14 00:13:39386} // namespace protocol
387} // namespace remoting