jingle_session_unittest.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "remoting/protocol/jingle_session.h"
6
7#include "base/bind.h"
8#include "base/message_loop/message_loop.h"
9#include "base/run_loop.h"
10#include "base/test/test_timeouts.h"
11#include "base/time/time.h"
12#include "jingle/glue/thread_wrapper.h"
13#include "net/socket/socket.h"
14#include "net/socket/stream_socket.h"
15#include "net/url_request/url_request_context_getter.h"
16#include "remoting/base/constants.h"
17#include "remoting/jingle_glue/chromium_port_allocator.h"
18#include "remoting/jingle_glue/fake_signal_strategy.h"
19#include "remoting/jingle_glue/network_settings.h"
20#include "remoting/protocol/authenticator.h"
21#include "remoting/protocol/channel_authenticator.h"
22#include "remoting/protocol/connection_tester.h"
23#include "remoting/protocol/fake_authenticator.h"
24#include "remoting/protocol/jingle_session_manager.h"
25#include "remoting/protocol/libjingle_transport_factory.h"
26#include "testing/gmock/include/gmock/gmock.h"
27#include "testing/gtest/include/gtest/gtest.h"
28
29using testing::_;
30using testing::AtLeast;
31using testing::AtMost;
32using testing::DeleteArg;
33using testing::DoAll;
34using testing::InSequence;
35using testing::Invoke;
36using testing::InvokeWithoutArgs;
37using testing::Return;
38using testing::SaveArg;
39using testing::SetArgumentPointee;
40using testing::WithArg;
41
42namespace remoting {
43namespace protocol {
44
45namespace {
46
47const char kHostJid[] = "host1@gmail.com/123";
48const char kClientJid[] = "host2@gmail.com/321";
49
50// Send 100 messages 1024 bytes each. UDP messages are sent with 10ms delay
51// between messages (about 1 second for 100 messages).
52const int kMessageSize = 1024;
53const int kMessages = 100;
54const char kChannelName[] = "test_channel";
55
56void QuitCurrentThread() {
57  base::MessageLoop::current()->PostTask(FROM_HERE,
58                                         base::MessageLoop::QuitClosure());
59}
60
61ACTION(QuitThread) {
62  QuitCurrentThread();
63}
64
65ACTION_P(QuitThreadOnCounter, counter) {
66  --(*counter);
67  EXPECT_GE(*counter, 0);
68  if (*counter == 0)
69    QuitCurrentThread();
70}
71
72class MockSessionManagerListener : public SessionManager::Listener {
73 public:
74  MOCK_METHOD0(OnSessionManagerReady, void());
75  MOCK_METHOD2(OnIncomingSession,
76               void(Session*,
77                    SessionManager::IncomingSessionResponse*));
78};
79
80class MockSessionEventHandler : public Session::EventHandler {
81 public:
82  MOCK_METHOD1(OnSessionStateChange, void(Session::State));
83  MOCK_METHOD2(OnSessionRouteChange, void(const std::string& channel_name,
84                                          const TransportRoute& route));
85};
86
87class MockStreamChannelCallback {
88 public:
89  MOCK_METHOD1(OnDone, void(net::StreamSocket* socket));
90};
91
92}  // namespace
93
94class JingleSessionTest : public testing::Test {
95 public:
96  JingleSessionTest() {
97    message_loop_.reset(new base::MessageLoopForIO());
98    jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
99  }
100
101  // Helper method that handles OnIncomingSession().
102  void SetHostSession(Session* session) {
103    DCHECK(session);
104    host_session_.reset(session);
105    host_session_->SetEventHandler(&host_session_event_handler_);
106
107    session->set_config(SessionConfig::ForTest());
108  }
109
110  void DeleteSession() {
111    host_session_.reset();
112  }
113
114  void OnClientChannelCreated(scoped_ptr<net::StreamSocket> socket) {
115    client_channel_callback_.OnDone(socket.get());
116    client_socket_ = socket.Pass();
117  }
118
119  void OnHostChannelCreated(scoped_ptr<net::StreamSocket> socket) {
120    host_channel_callback_.OnDone(socket.get());
121    host_socket_ = socket.Pass();
122  }
123
124 protected:
125  virtual void SetUp() {
126  }
127
128  virtual void TearDown() {
129    CloseSessions();
130    CloseSessionManager();
131    base::RunLoop().RunUntilIdle();
132  }
133
134  void CloseSessions() {
135    host_socket_.reset();
136    host_session_.reset();
137    client_socket_.reset();
138    client_session_.reset();
139  }
140
141  void CreateSessionManagers(int auth_round_trips, int messages_till_start,
142                        FakeAuthenticator::Action auth_action) {
143    host_signal_strategy_.reset(new FakeSignalStrategy(kHostJid));
144    client_signal_strategy_.reset(new FakeSignalStrategy(kClientJid));
145    FakeSignalStrategy::Connect(host_signal_strategy_.get(),
146                                client_signal_strategy_.get());
147
148    EXPECT_CALL(host_server_listener_, OnSessionManagerReady())
149        .Times(1);
150
151    NetworkSettings network_settings(NetworkSettings::NAT_TRAVERSAL_OUTGOING);
152
153    scoped_ptr<TransportFactory> host_transport(new LibjingleTransportFactory(
154        NULL,
155        ChromiumPortAllocator::Create(NULL, network_settings)
156            .PassAs<cricket::HttpPortAllocatorBase>(),
157        network_settings));
158    host_server_.reset(new JingleSessionManager(host_transport.Pass()));
159    host_server_->Init(host_signal_strategy_.get(), &host_server_listener_);
160
161    scoped_ptr<AuthenticatorFactory> factory(
162        new FakeHostAuthenticatorFactory(auth_round_trips,
163          messages_till_start, auth_action, true));
164    host_server_->set_authenticator_factory(factory.Pass());
165
166    EXPECT_CALL(client_server_listener_, OnSessionManagerReady())
167        .Times(1);
168    scoped_ptr<TransportFactory> client_transport(new LibjingleTransportFactory(
169        NULL,
170        ChromiumPortAllocator::Create(NULL, network_settings)
171            .PassAs<cricket::HttpPortAllocatorBase>(),
172        network_settings));
173    client_server_.reset(
174        new JingleSessionManager(client_transport.Pass()));
175    client_server_->Init(client_signal_strategy_.get(),
176                         &client_server_listener_);
177  }
178
179  void CreateSessionManagers(int auth_round_trips,
180                             FakeAuthenticator::Action auth_action) {
181    CreateSessionManagers(auth_round_trips, 0, auth_action);
182  }
183
184  void CloseSessionManager() {
185    if (host_server_.get()) {
186      host_server_->Close();
187      host_server_.reset();
188    }
189    if (client_server_.get()) {
190      client_server_->Close();
191      client_server_.reset();
192    }
193    host_signal_strategy_.reset();
194    client_signal_strategy_.reset();
195  }
196
197  void InitiateConnection(int auth_round_trips,
198                          FakeAuthenticator::Action auth_action,
199                          bool expect_fail) {
200    EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _))
201        .WillOnce(DoAll(
202            WithArg<0>(Invoke(this, &JingleSessionTest::SetHostSession)),
203            SetArgumentPointee<1>(protocol::SessionManager::ACCEPT)));
204
205    {
206      InSequence dummy;
207
208      EXPECT_CALL(host_session_event_handler_,
209                  OnSessionStateChange(Session::CONNECTED))
210          .Times(AtMost(1));
211      EXPECT_CALL(host_session_event_handler_,
212                  OnSessionStateChange(Session::AUTHENTICATING))
213          .Times(AtMost(1));
214      if (expect_fail) {
215        EXPECT_CALL(host_session_event_handler_,
216                    OnSessionStateChange(Session::FAILED))
217            .Times(1);
218      } else {
219        EXPECT_CALL(host_session_event_handler_,
220                    OnSessionStateChange(Session::AUTHENTICATED))
221            .Times(1);
222        // Expect that the connection will be closed eventually.
223        EXPECT_CALL(host_session_event_handler_,
224                    OnSessionStateChange(Session::CLOSED))
225            .Times(AtMost(1));
226      }
227    }
228
229    {
230      InSequence dummy;
231
232      EXPECT_CALL(client_session_event_handler_,
233                  OnSessionStateChange(Session::CONNECTED))
234          .Times(AtMost(1));
235      EXPECT_CALL(client_session_event_handler_,
236                  OnSessionStateChange(Session::AUTHENTICATING))
237          .Times(AtMost(1));
238      if (expect_fail) {
239        EXPECT_CALL(client_session_event_handler_,
240                    OnSessionStateChange(Session::FAILED))
241            .Times(1);
242      } else {
243        EXPECT_CALL(client_session_event_handler_,
244                    OnSessionStateChange(Session::AUTHENTICATED))
245            .Times(1);
246        // Expect that the connection will be closed eventually.
247        EXPECT_CALL(client_session_event_handler_,
248                    OnSessionStateChange(Session::CLOSED))
249            .Times(AtMost(1));
250      }
251    }
252
253    scoped_ptr<Authenticator> authenticator(new FakeAuthenticator(
254        FakeAuthenticator::CLIENT, auth_round_trips, auth_action, true));
255
256    client_session_ = client_server_->Connect(
257        kHostJid, authenticator.Pass(),
258        CandidateSessionConfig::CreateDefault());
259    client_session_->SetEventHandler(&client_session_event_handler_);
260
261    base::RunLoop().RunUntilIdle();
262  }
263
264  void CreateChannel() {
265    client_session_->GetTransportChannelFactory()->CreateStreamChannel(
266        kChannelName, base::Bind(&JingleSessionTest::OnClientChannelCreated,
267                                 base::Unretained(this)));
268    host_session_->GetTransportChannelFactory()->CreateStreamChannel(
269        kChannelName, base::Bind(&JingleSessionTest::OnHostChannelCreated,
270                                 base::Unretained(this)));
271
272    int counter = 2;
273    ExpectRouteChange(kChannelName);
274    EXPECT_CALL(client_channel_callback_, OnDone(_))
275        .WillOnce(QuitThreadOnCounter(&counter));
276    EXPECT_CALL(host_channel_callback_, OnDone(_))
277        .WillOnce(QuitThreadOnCounter(&counter));
278    message_loop_->Run();
279
280    EXPECT_TRUE(client_socket_.get());
281    EXPECT_TRUE(host_socket_.get());
282  }
283
284  void ExpectRouteChange(const std::string& channel_name) {
285    EXPECT_CALL(host_session_event_handler_,
286                OnSessionRouteChange(channel_name, _))
287        .Times(AtLeast(1));
288    EXPECT_CALL(client_session_event_handler_,
289                OnSessionRouteChange(channel_name, _))
290        .Times(AtLeast(1));
291  }
292
293  scoped_ptr<base::MessageLoopForIO> message_loop_;
294
295  scoped_ptr<FakeSignalStrategy> host_signal_strategy_;
296  scoped_ptr<FakeSignalStrategy> client_signal_strategy_;
297
298  scoped_ptr<JingleSessionManager> host_server_;
299  MockSessionManagerListener host_server_listener_;
300  scoped_ptr<JingleSessionManager> client_server_;
301  MockSessionManagerListener client_server_listener_;
302
303  scoped_ptr<Session> host_session_;
304  MockSessionEventHandler host_session_event_handler_;
305  scoped_ptr<Session> client_session_;
306  MockSessionEventHandler client_session_event_handler_;
307
308  MockStreamChannelCallback client_channel_callback_;
309  MockStreamChannelCallback host_channel_callback_;
310
311  scoped_ptr<net::StreamSocket> client_socket_;
312  scoped_ptr<net::StreamSocket> host_socket_;
313};
314
315
316// Verify that we can create and destroy session managers without a
317// connection.
318TEST_F(JingleSessionTest, CreateAndDestoy) {
319  CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
320}
321
322// Verify that an incoming session can be rejected, and that the
323// status of the connection is set to FAILED in this case.
324TEST_F(JingleSessionTest, RejectConnection) {
325  CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
326
327  // Reject incoming session.
328  EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _))
329      .WillOnce(SetArgumentPointee<1>(protocol::SessionManager::DECLINE));
330
331  {
332    InSequence dummy;
333    EXPECT_CALL(client_session_event_handler_,
334                OnSessionStateChange(Session::FAILED))
335        .Times(1);
336  }
337
338  scoped_ptr<Authenticator> authenticator(new FakeAuthenticator(
339      FakeAuthenticator::CLIENT, 1, FakeAuthenticator::ACCEPT, true));
340  client_session_ = client_server_->Connect(
341      kHostJid, authenticator.Pass(), CandidateSessionConfig::CreateDefault());
342  client_session_->SetEventHandler(&client_session_event_handler_);
343
344  base::RunLoop().RunUntilIdle();
345}
346
347// Verify that we can connect two endpoints with single-step authentication.
348TEST_F(JingleSessionTest, Connect) {
349  CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
350  InitiateConnection(1, FakeAuthenticator::ACCEPT, false);
351
352  // Verify that the client specified correct initiator value.
353  ASSERT_GT(host_signal_strategy_->received_messages().size(), 0U);
354  const buzz::XmlElement* initiate_xml =
355      host_signal_strategy_->received_messages().front();
356  const buzz::XmlElement* jingle_element =
357      initiate_xml->FirstNamed(buzz::QName(kJingleNamespace, "jingle"));
358  ASSERT_TRUE(jingle_element);
359  ASSERT_EQ(kClientJid,
360            jingle_element->Attr(buzz::QName(std::string(), "initiator")));
361}
362
363// Verify that we can connect two endpoints with multi-step authentication.
364TEST_F(JingleSessionTest, ConnectWithMultistep) {
365  CreateSessionManagers(3, FakeAuthenticator::ACCEPT);
366  InitiateConnection(3, FakeAuthenticator::ACCEPT, false);
367}
368
369// Verify that connection is terminated when single-step auth fails.
370TEST_F(JingleSessionTest, ConnectWithBadAuth) {
371  CreateSessionManagers(1, FakeAuthenticator::REJECT);
372  InitiateConnection(1, FakeAuthenticator::ACCEPT, true);
373}
374
375// Verify that connection is terminated when multi-step auth fails.
376TEST_F(JingleSessionTest, ConnectWithBadMultistepAuth) {
377  CreateSessionManagers(3, FakeAuthenticator::REJECT);
378  InitiateConnection(3, FakeAuthenticator::ACCEPT, true);
379}
380
381// Verify that data can be sent over stream channel.
382TEST_F(JingleSessionTest, TestStreamChannel) {
383  CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
384  ASSERT_NO_FATAL_FAILURE(
385      InitiateConnection(1, FakeAuthenticator::ACCEPT, false));
386
387  ASSERT_NO_FATAL_FAILURE(CreateChannel());
388
389  StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
390                                kMessageSize, kMessages);
391  tester.Start();
392  message_loop_->Run();
393  tester.CheckResults();
394}
395
396TEST_F(JingleSessionTest, DeleteSessionOnIncomingConnection) {
397  CreateSessionManagers(3, FakeAuthenticator::ACCEPT);
398
399  EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _))
400      .WillOnce(DoAll(
401          WithArg<0>(Invoke(this, &JingleSessionTest::SetHostSession)),
402          SetArgumentPointee<1>(protocol::SessionManager::ACCEPT)));
403
404  EXPECT_CALL(host_session_event_handler_,
405      OnSessionStateChange(Session::CONNECTED))
406      .Times(AtMost(1));
407
408  EXPECT_CALL(host_session_event_handler_,
409      OnSessionStateChange(Session::AUTHENTICATING))
410      .WillOnce(InvokeWithoutArgs(this, &JingleSessionTest::DeleteSession));
411
412  scoped_ptr<Authenticator> authenticator(new FakeAuthenticator(
413      FakeAuthenticator::CLIENT, 3, FakeAuthenticator::ACCEPT, true));
414
415  client_session_ = client_server_->Connect(
416      kHostJid, authenticator.Pass(),
417      CandidateSessionConfig::CreateDefault());
418
419  base::RunLoop().RunUntilIdle();
420}
421
422TEST_F(JingleSessionTest, DeleteSessionOnAuth) {
423  // Same as the previous test, but set messages_till_started to 2 in
424  // CreateSessionManagers so that the session will goes into the
425  // AUTHENTICATING state after two message exchanges.
426  CreateSessionManagers(3, 2, FakeAuthenticator::ACCEPT);
427
428  EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _))
429      .WillOnce(DoAll(
430          WithArg<0>(Invoke(this, &JingleSessionTest::SetHostSession)),
431          SetArgumentPointee<1>(protocol::SessionManager::ACCEPT)));
432
433  EXPECT_CALL(host_session_event_handler_,
434      OnSessionStateChange(Session::CONNECTED))
435      .Times(AtMost(1));
436
437  EXPECT_CALL(host_session_event_handler_,
438      OnSessionStateChange(Session::AUTHENTICATING))
439      .WillOnce(InvokeWithoutArgs(this, &JingleSessionTest::DeleteSession));
440
441  scoped_ptr<Authenticator> authenticator(new FakeAuthenticator(
442      FakeAuthenticator::CLIENT, 3, FakeAuthenticator::ACCEPT, true));
443
444  client_session_ = client_server_->Connect(
445      kHostJid, authenticator.Pass(),
446      CandidateSessionConfig::CreateDefault());
447  base::RunLoop().RunUntilIdle();
448}
449
450// Verify that data can be sent over a multiplexed channel.
451TEST_F(JingleSessionTest, TestMuxStreamChannel) {
452  CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
453  ASSERT_NO_FATAL_FAILURE(
454      InitiateConnection(1, FakeAuthenticator::ACCEPT, false));
455
456  client_session_->GetMultiplexedChannelFactory()->CreateStreamChannel(
457      kChannelName, base::Bind(&JingleSessionTest::OnClientChannelCreated,
458                               base::Unretained(this)));
459  host_session_->GetMultiplexedChannelFactory()->CreateStreamChannel(
460      kChannelName, base::Bind(&JingleSessionTest::OnHostChannelCreated,
461                               base::Unretained(this)));
462
463  int counter = 2;
464  ExpectRouteChange("mux");
465  EXPECT_CALL(client_channel_callback_, OnDone(_))
466      .WillOnce(QuitThreadOnCounter(&counter));
467  EXPECT_CALL(host_channel_callback_, OnDone(_))
468      .WillOnce(QuitThreadOnCounter(&counter));
469  message_loop_->Run();
470
471  EXPECT_TRUE(client_socket_.get());
472  EXPECT_TRUE(host_socket_.get());
473
474  StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
475                                kMessageSize, kMessages);
476  tester.Start();
477  message_loop_->Run();
478  tester.CheckResults();
479}
480
481// Verify that we can connect channels with multistep auth.
482TEST_F(JingleSessionTest, TestMultistepAuthStreamChannel) {
483  CreateSessionManagers(3, FakeAuthenticator::ACCEPT);
484  ASSERT_NO_FATAL_FAILURE(
485      InitiateConnection(3, FakeAuthenticator::ACCEPT, false));
486
487  ASSERT_NO_FATAL_FAILURE(CreateChannel());
488
489  StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
490                                kMessageSize, kMessages);
491  tester.Start();
492  message_loop_->Run();
493  tester.CheckResults();
494}
495
496// Verify that we shutdown properly when channel authentication fails.
497TEST_F(JingleSessionTest, TestFailedChannelAuth) {
498  CreateSessionManagers(1, FakeAuthenticator::REJECT_CHANNEL);
499  ASSERT_NO_FATAL_FAILURE(
500      InitiateConnection(1, FakeAuthenticator::ACCEPT, false));
501
502  client_session_->GetTransportChannelFactory()->CreateStreamChannel(
503      kChannelName, base::Bind(&JingleSessionTest::OnClientChannelCreated,
504                               base::Unretained(this)));
505  host_session_->GetTransportChannelFactory()->CreateStreamChannel(
506      kChannelName, base::Bind(&JingleSessionTest::OnHostChannelCreated,
507                               base::Unretained(this)));
508
509  // Terminate the message loop when we get rejection notification
510  // from the host.
511  EXPECT_CALL(host_channel_callback_, OnDone(NULL))
512      .WillOnce(QuitThread());
513  EXPECT_CALL(client_channel_callback_, OnDone(_))
514      .Times(AtMost(1));
515  ExpectRouteChange(kChannelName);
516
517  message_loop_->Run();
518
519  EXPECT_TRUE(!host_socket_.get());
520}
521
522}  // namespace protocol
523}  // namespace remoting
524