• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "jingle/notifier/base/xmpp_connection.h"
6 
7 #include <string>
8 #include <vector>
9 
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 "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"
24 
25 namespace buzz {
26 class CaptchaChallenge;
27 class Jid;
28 }  // namespace buzz
29 
30 namespace talk_base {
31 class CryptString;
32 class SocketAddress;
33 class Task;
34 }  // namespace talk_base
35 
36 namespace notifier {
37 
38 using ::testing::_;
39 using ::testing::Return;
40 using ::testing::SaveArg;
41 
42 class MockPreXmppAuth : public buzz::PreXmppAuth {
43  public:
~MockPreXmppAuth()44   virtual ~MockPreXmppAuth() {}
45 
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&,
54                     const std::string&,
55                     const std::string&));
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());
63 };
64 
65 class MockXmppConnectionDelegate : public XmppConnection::Delegate {
66  public:
~MockXmppConnectionDelegate()67   virtual ~MockXmppConnectionDelegate() {}
68 
69   MOCK_METHOD1(OnConnect, void(base::WeakPtr<buzz::XmppTaskParentInterface>));
70   MOCK_METHOD3(OnError,
71                void(buzz::XmppEngine::Error, int, const buzz::XmlElement*));
72 };
73 
74 class XmppConnectionTest : public testing::Test {
75  protected:
XmppConnectionTest()76   XmppConnectionTest()
77       : mock_pre_xmpp_auth_(new MockPreXmppAuth()),
78         url_request_context_getter_(new net::TestURLRequestContextGetter(
79             message_loop_.message_loop_proxy())) {}
80 
~XmppConnectionTest()81   virtual ~XmppConnectionTest() {}
82 
TearDown()83   virtual void TearDown() {
84     // Clear out any messages posted by XmppConnection's destructor.
85     message_loop_.RunUntilIdle();
86   }
87 
88   // Needed by XmppConnection.
89   base::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_;
93 };
94 
TEST_F(XmppConnectionTest,CreateDestroy)95 TEST_F(XmppConnectionTest, CreateDestroy) {
96   XmppConnection xmpp_connection(buzz::XmppClientSettings(),
97                                  url_request_context_getter_,
98                                  &mock_xmpp_connection_delegate_, NULL);
99 }
100 
101 #if !defined(_MSC_VER) || _MSC_VER < 1700 // http://crbug.com/158570
TEST_F(XmppConnectionTest,ImmediateFailure)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));
108 
109   XmppConnection xmpp_connection(buzz::XmppClientSettings(),
110                                  url_request_context_getter_,
111                                  &mock_xmpp_connection_delegate_, NULL);
112 
113   // We need to do this *before* |xmpp_connection| gets destroyed or
114   // our delegate won't be called.
115   message_loop_.RunUntilIdle();
116 }
117 
TEST_F(XmppConnectionTest,PreAuthFailure)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));
124 
125   EXPECT_CALL(mock_xmpp_connection_delegate_,
126               OnError(buzz::XmppEngine::ERROR_AUTH, 5, NULL));
127 
128   XmppConnection xmpp_connection(
129       buzz::XmppClientSettings(), url_request_context_getter_,
130       &mock_xmpp_connection_delegate_, mock_pre_xmpp_auth_.release());
131 
132   // We need to do this *before* |xmpp_connection| gets destroyed or
133   // our delegate won't be called.
134   message_loop_.RunUntilIdle();
135 }
136 
TEST_F(XmppConnectionTest,FailureAfterPreAuth)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(""));
143 
144   EXPECT_CALL(mock_xmpp_connection_delegate_,
145               OnError(buzz::XmppEngine::ERROR_NONE, 0, NULL));
146 
147   XmppConnection xmpp_connection(
148       buzz::XmppClientSettings(), url_request_context_getter_,
149       &mock_xmpp_connection_delegate_, mock_pre_xmpp_auth_.release());
150 
151   // We need to do this *before* |xmpp_connection| gets destroyed or
152   // our delegate won't be called.
153   message_loop_.RunUntilIdle();
154 }
155 
TEST_F(XmppConnectionTest,RaisedError)156 TEST_F(XmppConnectionTest, RaisedError) {
157   EXPECT_CALL(mock_xmpp_connection_delegate_,
158               OnError(buzz::XmppEngine::ERROR_NONE, 0, NULL));
159 
160   XmppConnection xmpp_connection(buzz::XmppClientSettings(),
161                                  url_request_context_getter_,
162                                  &mock_xmpp_connection_delegate_, NULL);
163 
164   xmpp_connection.weak_xmpp_client_->
165       SignalStateChange(buzz::XmppEngine::STATE_CLOSED);
166 }
167 #endif
168 
TEST_F(XmppConnectionTest,Connect)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));
173 
174   {
175     XmppConnection xmpp_connection(buzz::XmppClientSettings(),
176                                    url_request_context_getter_,
177                                    &mock_xmpp_connection_delegate_, NULL);
178 
179     xmpp_connection.weak_xmpp_client_->
180         SignalStateChange(buzz::XmppEngine::STATE_OPEN);
181     EXPECT_EQ(xmpp_connection.weak_xmpp_client_.get(), weak_ptr.get());
182   }
183 
184   EXPECT_EQ(NULL, weak_ptr.get());
185 }
186 
TEST_F(XmppConnectionTest,MultipleConnect)187 TEST_F(XmppConnectionTest, MultipleConnect) {
188   EXPECT_DEBUG_DEATH({
189     base::WeakPtr<talk_base::Task> weak_ptr;
190     EXPECT_CALL(mock_xmpp_connection_delegate_, OnConnect(_)).
191         WillOnce(SaveArg<0>(&weak_ptr));
192 
193     XmppConnection xmpp_connection(buzz::XmppClientSettings(),
194                                    url_request_context_getter_,
195                                    &mock_xmpp_connection_delegate_, NULL);
196 
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);
202     }
203 
204     EXPECT_EQ(xmpp_connection.weak_xmpp_client_.get(), weak_ptr.get());
205   }, "more than once");
206 }
207 
208 #if !defined(_MSC_VER) || _MSC_VER < 1700 // http://crbug.com/158570
TEST_F(XmppConnectionTest,ConnectThenError)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));
215 
216   XmppConnection xmpp_connection(buzz::XmppClientSettings(),
217                                  url_request_context_getter_,
218                                  &mock_xmpp_connection_delegate_, NULL);
219 
220   xmpp_connection.weak_xmpp_client_->
221       SignalStateChange(buzz::XmppEngine::STATE_OPEN);
222   EXPECT_EQ(xmpp_connection.weak_xmpp_client_.get(), weak_ptr.get());
223 
224   xmpp_connection.weak_xmpp_client_->
225       SignalStateChange(buzz::XmppEngine::STATE_CLOSED);
226   EXPECT_EQ(NULL, weak_ptr.get());
227 }
228 #endif
229 
230 // We don't destroy XmppConnection's task pump on destruction, but it
231 // should still not run any more tasks.
TEST_F(XmppConnectionTest,TasksDontRunAfterXmppConnectionDestructor)232 TEST_F(XmppConnectionTest, TasksDontRunAfterXmppConnectionDestructor) {
233   {
234     XmppConnection xmpp_connection(buzz::XmppClientSettings(),
235                                    url_request_context_getter_,
236                                    &mock_xmpp_connection_delegate_, NULL);
237 
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
241     // talk_base::Task.
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);
246     task->Start();
247   }
248 
249   // This should destroy |task_pump|, but |task| still shouldn't run.
250   message_loop_.RunUntilIdle();
251 }
252 
253 }  // namespace notifier
254