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.h"
14 #include "jingle/glue/mock_task.h"
15 #include "jingle/glue/task_pump.h"
16 #include "jingle/notifier/base/weak_xmpp_client.h"
17 #include "net/cert/cert_verifier.h"
18 #include "net/url_request/url_request_context_getter.h"
19 #include "net/url_request/url_request_test_util.h"
20 #include "talk/xmpp/prexmppauth.h"
21 #include "talk/xmpp/xmppclientsettings.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
26 class CaptchaChallenge
;
34 } // namespace talk_base
39 using ::testing::Return
;
40 using ::testing::SaveArg
;
42 class MockPreXmppAuth
: public buzz::PreXmppAuth
{
44 virtual ~MockPreXmppAuth() {}
46 MOCK_METHOD2(ChooseBestSaslMechanism
,
47 std::string(const std::vector
<std::string
>&, bool));
48 MOCK_METHOD1(CreateSaslMechanism
,
49 buzz::SaslMechanism
*(const std::string
&));
50 MOCK_METHOD5(StartPreXmppAuth
,
51 void(const buzz::Jid
&,
52 const talk_base::SocketAddress
&,
53 const talk_base::CryptString
&,
56 MOCK_CONST_METHOD0(IsAuthDone
, bool());
57 MOCK_CONST_METHOD0(IsAuthorized
, bool());
58 MOCK_CONST_METHOD0(HadError
, bool());
59 MOCK_CONST_METHOD0(GetError
, int());
60 MOCK_CONST_METHOD0(GetCaptchaChallenge
, buzz::CaptchaChallenge());
61 MOCK_CONST_METHOD0(GetAuthToken
, std::string());
62 MOCK_CONST_METHOD0(GetAuthMechanism
, std::string());
65 class MockXmppConnectionDelegate
: public XmppConnection::Delegate
{
67 virtual ~MockXmppConnectionDelegate() {}
69 MOCK_METHOD1(OnConnect
, void(base::WeakPtr
<buzz::XmppTaskParentInterface
>));
71 void(buzz::XmppEngine::Error
, int, const buzz::XmlElement
*));
74 class XmppConnectionTest
: public testing::Test
{
77 : mock_pre_xmpp_auth_(new MockPreXmppAuth()),
78 url_request_context_getter_(new net::TestURLRequestContextGetter(
79 message_loop_
.message_loop_proxy())) {}
81 virtual ~XmppConnectionTest() {}
83 virtual void TearDown() {
84 // Clear out any messages posted by XmppConnection's destructor.
85 message_loop_
.RunUntilIdle();
88 // Needed by XmppConnection.
89 MessageLoop message_loop_
;
90 MockXmppConnectionDelegate mock_xmpp_connection_delegate_
;
91 scoped_ptr
<MockPreXmppAuth
> mock_pre_xmpp_auth_
;
92 scoped_refptr
<net::TestURLRequestContextGetter
> url_request_context_getter_
;
95 TEST_F(XmppConnectionTest
, CreateDestroy
) {
96 XmppConnection
xmpp_connection(buzz::XmppClientSettings(),
97 url_request_context_getter_
,
98 &mock_xmpp_connection_delegate_
, NULL
);
101 #if !defined(_MSC_VER) || _MSC_VER < 1700 // http://crbug.com/158570
102 TEST_F(XmppConnectionTest
, ImmediateFailure
) {
103 // ChromeAsyncSocket::Connect() will always return false since we're
104 // not setting a valid host, but this gets bubbled up as ERROR_NONE
105 // due to XmppClient's inconsistent error-handling.
106 EXPECT_CALL(mock_xmpp_connection_delegate_
,
107 OnError(buzz::XmppEngine::ERROR_NONE
, 0, NULL
));
109 XmppConnection
xmpp_connection(buzz::XmppClientSettings(),
110 url_request_context_getter_
,
111 &mock_xmpp_connection_delegate_
, NULL
);
113 // We need to do this *before* |xmpp_connection| gets destroyed or
114 // our delegate won't be called.
115 message_loop_
.RunUntilIdle();
118 TEST_F(XmppConnectionTest
, PreAuthFailure
) {
119 EXPECT_CALL(*mock_pre_xmpp_auth_
, StartPreXmppAuth(_
, _
, _
, _
,_
));
120 EXPECT_CALL(*mock_pre_xmpp_auth_
, IsAuthDone()).WillOnce(Return(true));
121 EXPECT_CALL(*mock_pre_xmpp_auth_
, IsAuthorized()).WillOnce(Return(false));
122 EXPECT_CALL(*mock_pre_xmpp_auth_
, HadError()).WillOnce(Return(true));
123 EXPECT_CALL(*mock_pre_xmpp_auth_
, GetError()).WillOnce(Return(5));
125 EXPECT_CALL(mock_xmpp_connection_delegate_
,
126 OnError(buzz::XmppEngine::ERROR_AUTH
, 5, NULL
));
128 XmppConnection
xmpp_connection(
129 buzz::XmppClientSettings(), url_request_context_getter_
,
130 &mock_xmpp_connection_delegate_
, mock_pre_xmpp_auth_
.release());
132 // We need to do this *before* |xmpp_connection| gets destroyed or
133 // our delegate won't be called.
134 message_loop_
.RunUntilIdle();
137 TEST_F(XmppConnectionTest
, FailureAfterPreAuth
) {
138 EXPECT_CALL(*mock_pre_xmpp_auth_
, StartPreXmppAuth(_
, _
, _
, _
,_
));
139 EXPECT_CALL(*mock_pre_xmpp_auth_
, IsAuthDone()).WillOnce(Return(true));
140 EXPECT_CALL(*mock_pre_xmpp_auth_
, IsAuthorized()).WillOnce(Return(true));
141 EXPECT_CALL(*mock_pre_xmpp_auth_
, GetAuthMechanism()).WillOnce(Return(""));
142 EXPECT_CALL(*mock_pre_xmpp_auth_
, GetAuthToken()).WillOnce(Return(""));
144 EXPECT_CALL(mock_xmpp_connection_delegate_
,
145 OnError(buzz::XmppEngine::ERROR_NONE
, 0, NULL
));
147 XmppConnection
xmpp_connection(
148 buzz::XmppClientSettings(), url_request_context_getter_
,
149 &mock_xmpp_connection_delegate_
, mock_pre_xmpp_auth_
.release());
151 // We need to do this *before* |xmpp_connection| gets destroyed or
152 // our delegate won't be called.
153 message_loop_
.RunUntilIdle();
156 TEST_F(XmppConnectionTest
, RaisedError
) {
157 EXPECT_CALL(mock_xmpp_connection_delegate_
,
158 OnError(buzz::XmppEngine::ERROR_NONE
, 0, NULL
));
160 XmppConnection
xmpp_connection(buzz::XmppClientSettings(),
161 url_request_context_getter_
,
162 &mock_xmpp_connection_delegate_
, NULL
);
164 xmpp_connection
.weak_xmpp_client_
->
165 SignalStateChange(buzz::XmppEngine::STATE_CLOSED
);
169 TEST_F(XmppConnectionTest
, Connect
) {
170 base::WeakPtr
<talk_base::Task
> weak_ptr
;
171 EXPECT_CALL(mock_xmpp_connection_delegate_
, OnConnect(_
)).
172 WillOnce(SaveArg
<0>(&weak_ptr
));
175 XmppConnection
xmpp_connection(buzz::XmppClientSettings(),
176 url_request_context_getter_
,
177 &mock_xmpp_connection_delegate_
, NULL
);
179 xmpp_connection
.weak_xmpp_client_
->
180 SignalStateChange(buzz::XmppEngine::STATE_OPEN
);
181 EXPECT_EQ(xmpp_connection
.weak_xmpp_client_
.get(), weak_ptr
.get());
184 EXPECT_EQ(NULL
, weak_ptr
.get());
187 TEST_F(XmppConnectionTest
, MultipleConnect
) {
189 base::WeakPtr
<talk_base::Task
> weak_ptr
;
190 EXPECT_CALL(mock_xmpp_connection_delegate_
, OnConnect(_
)).
191 WillOnce(SaveArg
<0>(&weak_ptr
));
193 XmppConnection
xmpp_connection(buzz::XmppClientSettings(),
194 url_request_context_getter_
,
195 &mock_xmpp_connection_delegate_
, NULL
);
197 xmpp_connection
.weak_xmpp_client_
->
198 SignalStateChange(buzz::XmppEngine::STATE_OPEN
);
199 for (int i
= 0; i
< 3; ++i
) {
200 xmpp_connection
.weak_xmpp_client_
->
201 SignalStateChange(buzz::XmppEngine::STATE_OPEN
);
204 EXPECT_EQ(xmpp_connection
.weak_xmpp_client_
.get(), weak_ptr
.get());
205 }, "more than once");
208 #if !defined(_MSC_VER) || _MSC_VER < 1700 // http://crbug.com/158570
209 TEST_F(XmppConnectionTest
, ConnectThenError
) {
210 base::WeakPtr
<talk_base::Task
> weak_ptr
;
211 EXPECT_CALL(mock_xmpp_connection_delegate_
, OnConnect(_
)).
212 WillOnce(SaveArg
<0>(&weak_ptr
));
213 EXPECT_CALL(mock_xmpp_connection_delegate_
,
214 OnError(buzz::XmppEngine::ERROR_NONE
, 0, NULL
));
216 XmppConnection
xmpp_connection(buzz::XmppClientSettings(),
217 url_request_context_getter_
,
218 &mock_xmpp_connection_delegate_
, NULL
);
220 xmpp_connection
.weak_xmpp_client_
->
221 SignalStateChange(buzz::XmppEngine::STATE_OPEN
);
222 EXPECT_EQ(xmpp_connection
.weak_xmpp_client_
.get(), weak_ptr
.get());
224 xmpp_connection
.weak_xmpp_client_
->
225 SignalStateChange(buzz::XmppEngine::STATE_CLOSED
);
226 EXPECT_EQ(NULL
, weak_ptr
.get());
230 // We don't destroy XmppConnection's task pump on destruction, but it
231 // should still not run any more tasks.
232 TEST_F(XmppConnectionTest
, TasksDontRunAfterXmppConnectionDestructor
) {
234 XmppConnection
xmpp_connection(buzz::XmppClientSettings(),
235 url_request_context_getter_
,
236 &mock_xmpp_connection_delegate_
, NULL
);
238 jingle_glue::MockTask
* task
=
239 new jingle_glue::MockTask(xmpp_connection
.task_pump_
.get());
240 // We have to do this since the state enum is protected in
242 const int TASK_STATE_ERROR
= 3;
243 ON_CALL(*task
, ProcessStart())
244 .WillByDefault(Return(TASK_STATE_ERROR
));
245 EXPECT_CALL(*task
, ProcessStart()).Times(0);
249 // This should destroy |task_pump|, but |task| still shouldn't run.
250 message_loop_
.RunUntilIdle();
253 } // namespace notifier