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.
5 #include "jingle/notifier/base/xmpp_connection.h"
10 #include "base/basictypes.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/message_loop/message_pump_default.h"
15 #include "jingle/glue/mock_task.h"
16 #include "jingle/glue/task_pump.h"
17 #include "jingle/notifier/base/weak_xmpp_client.h"
18 #include "net/cert/cert_verifier.h"
19 #include "net/url_request/url_request_context_getter.h"
20 #include "net/url_request/url_request_test_util.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "webrtc/libjingle/xmpp/prexmppauth.h"
24 #include "webrtc/libjingle/xmpp/xmppclientsettings.h"
27 class CaptchaChallenge
;
40 using ::testing::Return
;
41 using ::testing::SaveArg
;
43 class MockPreXmppAuth
: public buzz::PreXmppAuth
{
45 virtual ~MockPreXmppAuth() {}
47 MOCK_METHOD2(ChooseBestSaslMechanism
,
48 std::string(const std::vector
<std::string
>&, bool));
49 MOCK_METHOD1(CreateSaslMechanism
,
50 buzz::SaslMechanism
*(const std::string
&));
51 MOCK_METHOD5(StartPreXmppAuth
,
52 void(const buzz::Jid
&,
53 const rtc::SocketAddress
&,
54 const rtc::CryptString
&,
57 MOCK_CONST_METHOD0(IsAuthDone
, bool());
58 MOCK_CONST_METHOD0(IsAuthorized
, bool());
59 MOCK_CONST_METHOD0(HadError
, bool());
60 MOCK_CONST_METHOD0(GetError
, int());
61 MOCK_CONST_METHOD0(GetCaptchaChallenge
, buzz::CaptchaChallenge());
62 MOCK_CONST_METHOD0(GetAuthToken
, std::string());
63 MOCK_CONST_METHOD0(GetAuthMechanism
, std::string());
66 class MockXmppConnectionDelegate
: public XmppConnection::Delegate
{
68 virtual ~MockXmppConnectionDelegate() {}
70 MOCK_METHOD1(OnConnect
, void(base::WeakPtr
<buzz::XmppTaskParentInterface
>));
72 void(buzz::XmppEngine::Error
, int, const buzz::XmlElement
*));
75 class XmppConnectionTest
: public testing::Test
{
78 : mock_pre_xmpp_auth_(new MockPreXmppAuth()) {
79 scoped_ptr
<base::MessagePump
> pump(new base::MessagePumpDefault());
80 message_loop_
.reset(new base::MessageLoop(pump
.Pass()));
82 url_request_context_getter_
= new net::TestURLRequestContextGetter(
83 message_loop_
->task_runner());
86 ~XmppConnectionTest() override
{}
88 void TearDown() override
{
89 // Clear out any messages posted by XmppConnection's destructor.
90 message_loop_
->RunUntilIdle();
93 // Needed by XmppConnection.
94 scoped_ptr
<base::MessageLoop
> message_loop_
;
95 MockXmppConnectionDelegate mock_xmpp_connection_delegate_
;
96 scoped_ptr
<MockPreXmppAuth
> mock_pre_xmpp_auth_
;
97 scoped_refptr
<net::TestURLRequestContextGetter
> url_request_context_getter_
;
100 TEST_F(XmppConnectionTest
, CreateDestroy
) {
101 XmppConnection
xmpp_connection(buzz::XmppClientSettings(),
102 url_request_context_getter_
,
103 &mock_xmpp_connection_delegate_
, NULL
);
106 #if !defined(_MSC_VER) // http://crbug.com/158570
107 TEST_F(XmppConnectionTest
, ImmediateFailure
) {
108 // ChromeAsyncSocket::Connect() will always return false since we're
109 // not setting a valid host, but this gets bubbled up as ERROR_NONE
110 // due to XmppClient's inconsistent error-handling.
111 EXPECT_CALL(mock_xmpp_connection_delegate_
,
112 OnError(buzz::XmppEngine::ERROR_NONE
, 0, NULL
));
114 XmppConnection
xmpp_connection(buzz::XmppClientSettings(),
115 url_request_context_getter_
,
116 &mock_xmpp_connection_delegate_
, NULL
);
118 // We need to do this *before* |xmpp_connection| gets destroyed or
119 // our delegate won't be called.
120 message_loop_
->RunUntilIdle();
123 TEST_F(XmppConnectionTest
, PreAuthFailure
) {
124 EXPECT_CALL(*mock_pre_xmpp_auth_
, StartPreXmppAuth(_
, _
, _
, _
,_
));
125 EXPECT_CALL(*mock_pre_xmpp_auth_
, IsAuthDone()).WillOnce(Return(true));
126 EXPECT_CALL(*mock_pre_xmpp_auth_
, IsAuthorized()).WillOnce(Return(false));
127 EXPECT_CALL(*mock_pre_xmpp_auth_
, HadError()).WillOnce(Return(true));
128 EXPECT_CALL(*mock_pre_xmpp_auth_
, GetError()).WillOnce(Return(5));
130 EXPECT_CALL(mock_xmpp_connection_delegate_
,
131 OnError(buzz::XmppEngine::ERROR_AUTH
, 5, NULL
));
133 XmppConnection
xmpp_connection(
134 buzz::XmppClientSettings(), url_request_context_getter_
,
135 &mock_xmpp_connection_delegate_
, mock_pre_xmpp_auth_
.release());
137 // We need to do this *before* |xmpp_connection| gets destroyed or
138 // our delegate won't be called.
139 message_loop_
->RunUntilIdle();
142 TEST_F(XmppConnectionTest
, FailureAfterPreAuth
) {
143 EXPECT_CALL(*mock_pre_xmpp_auth_
, StartPreXmppAuth(_
, _
, _
, _
,_
));
144 EXPECT_CALL(*mock_pre_xmpp_auth_
, IsAuthDone()).WillOnce(Return(true));
145 EXPECT_CALL(*mock_pre_xmpp_auth_
, IsAuthorized()).WillOnce(Return(true));
146 EXPECT_CALL(*mock_pre_xmpp_auth_
, GetAuthMechanism()).WillOnce(Return(""));
147 EXPECT_CALL(*mock_pre_xmpp_auth_
, GetAuthToken()).WillOnce(Return(""));
149 EXPECT_CALL(mock_xmpp_connection_delegate_
,
150 OnError(buzz::XmppEngine::ERROR_NONE
, 0, NULL
));
152 XmppConnection
xmpp_connection(
153 buzz::XmppClientSettings(), url_request_context_getter_
,
154 &mock_xmpp_connection_delegate_
, mock_pre_xmpp_auth_
.release());
156 // We need to do this *before* |xmpp_connection| gets destroyed or
157 // our delegate won't be called.
158 message_loop_
->RunUntilIdle();
161 TEST_F(XmppConnectionTest
, RaisedError
) {
162 EXPECT_CALL(mock_xmpp_connection_delegate_
,
163 OnError(buzz::XmppEngine::ERROR_NONE
, 0, NULL
));
165 XmppConnection
xmpp_connection(buzz::XmppClientSettings(),
166 url_request_context_getter_
,
167 &mock_xmpp_connection_delegate_
, NULL
);
169 xmpp_connection
.weak_xmpp_client_
->
170 SignalStateChange(buzz::XmppEngine::STATE_CLOSED
);
174 TEST_F(XmppConnectionTest
, Connect
) {
175 base::WeakPtr
<rtc::Task
> weak_ptr
;
176 EXPECT_CALL(mock_xmpp_connection_delegate_
, OnConnect(_
)).
177 WillOnce(SaveArg
<0>(&weak_ptr
));
180 XmppConnection
xmpp_connection(buzz::XmppClientSettings(),
181 url_request_context_getter_
,
182 &mock_xmpp_connection_delegate_
, NULL
);
184 xmpp_connection
.weak_xmpp_client_
->
185 SignalStateChange(buzz::XmppEngine::STATE_OPEN
);
186 EXPECT_EQ(xmpp_connection
.weak_xmpp_client_
.get(), weak_ptr
.get());
189 EXPECT_EQ(NULL
, weak_ptr
.get());
192 TEST_F(XmppConnectionTest
, MultipleConnect
) {
194 base::WeakPtr
<rtc::Task
> weak_ptr
;
195 EXPECT_CALL(mock_xmpp_connection_delegate_
, OnConnect(_
)).
196 WillOnce(SaveArg
<0>(&weak_ptr
));
198 XmppConnection
xmpp_connection(buzz::XmppClientSettings(),
199 url_request_context_getter_
,
200 &mock_xmpp_connection_delegate_
, NULL
);
202 xmpp_connection
.weak_xmpp_client_
->
203 SignalStateChange(buzz::XmppEngine::STATE_OPEN
);
204 for (int i
= 0; i
< 3; ++i
) {
205 xmpp_connection
.weak_xmpp_client_
->
206 SignalStateChange(buzz::XmppEngine::STATE_OPEN
);
209 EXPECT_EQ(xmpp_connection
.weak_xmpp_client_
.get(), weak_ptr
.get());
210 }, "more than once");
213 #if !defined(_MSC_VER) // http://crbug.com/158570
214 TEST_F(XmppConnectionTest
, ConnectThenError
) {
215 base::WeakPtr
<rtc::Task
> weak_ptr
;
216 EXPECT_CALL(mock_xmpp_connection_delegate_
, OnConnect(_
)).
217 WillOnce(SaveArg
<0>(&weak_ptr
));
218 EXPECT_CALL(mock_xmpp_connection_delegate_
,
219 OnError(buzz::XmppEngine::ERROR_NONE
, 0, NULL
));
221 XmppConnection
xmpp_connection(buzz::XmppClientSettings(),
222 url_request_context_getter_
,
223 &mock_xmpp_connection_delegate_
, NULL
);
225 xmpp_connection
.weak_xmpp_client_
->
226 SignalStateChange(buzz::XmppEngine::STATE_OPEN
);
227 EXPECT_EQ(xmpp_connection
.weak_xmpp_client_
.get(), weak_ptr
.get());
229 xmpp_connection
.weak_xmpp_client_
->
230 SignalStateChange(buzz::XmppEngine::STATE_CLOSED
);
231 EXPECT_EQ(NULL
, weak_ptr
.get());
235 // We don't destroy XmppConnection's task pump on destruction, but it
236 // should still not run any more tasks.
237 TEST_F(XmppConnectionTest
, TasksDontRunAfterXmppConnectionDestructor
) {
239 XmppConnection
xmpp_connection(buzz::XmppClientSettings(),
240 url_request_context_getter_
,
241 &mock_xmpp_connection_delegate_
, NULL
);
243 jingle_glue::MockTask
* task
=
244 new jingle_glue::MockTask(xmpp_connection
.task_pump_
.get());
245 // We have to do this since the state enum is protected in
247 const int TASK_STATE_ERROR
= 3;
248 ON_CALL(*task
, ProcessStart())
249 .WillByDefault(Return(TASK_STATE_ERROR
));
250 EXPECT_CALL(*task
, ProcessStart()).Times(0);
254 // This should destroy |task_pump|, but |task| still shouldn't run.
255 message_loop_
->RunUntilIdle();
258 } // namespace notifier