Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / xmpp / xmpplogintask_unittest.cc
1 // Copyright 2004 Google Inc. All Rights Reserved
2
3
4 #include <iostream>
5 #include <sstream>
6 #include <string>
7 #include "webrtc/libjingle/xmllite/xmlelement.h"
8 #include "webrtc/libjingle/xmpp/constants.h"
9 #include "webrtc/libjingle/xmpp/plainsaslhandler.h"
10 #include "webrtc/libjingle/xmpp/saslplainmechanism.h"
11 #include "webrtc/libjingle/xmpp/util_unittest.h"
12 #include "webrtc/libjingle/xmpp/xmppengine.h"
13 #include "webrtc/base/common.h"
14 #include "webrtc/base/cryptstring.h"
15 #include "webrtc/base/gunit.h"
16
17 using buzz::Jid;
18 using buzz::QName;
19 using buzz::XmlElement;
20 using buzz::XmppEngine;
21 using buzz::XmppTestHandler;
22
23 enum XlttStage {
24   XLTT_STAGE_CONNECT = 0,
25   XLTT_STAGE_STREAMSTART,
26   XLTT_STAGE_TLS_FEATURES,
27   XLTT_STAGE_TLS_PROCEED,
28   XLTT_STAGE_ENCRYPTED_START,
29   XLTT_STAGE_AUTH_FEATURES,
30   XLTT_STAGE_AUTH_SUCCESS,
31   XLTT_STAGE_AUTHENTICATED_START,
32   XLTT_STAGE_BIND_FEATURES,
33   XLTT_STAGE_BIND_SUCCESS,
34   XLTT_STAGE_SESSION_SUCCESS,
35 };
36
37 class XmppLoginTaskTest : public testing::Test {
38  public:
39   XmppEngine* engine() { return engine_.get(); }
40   XmppTestHandler* handler() { return handler_.get(); }
41   virtual void SetUp() {
42     engine_.reset(XmppEngine::Create());
43     handler_.reset(new XmppTestHandler(engine_.get()));
44
45     Jid jid("david@my-server");
46     rtc::InsecureCryptStringImpl pass;
47     pass.password() = "david";
48     engine_->SetSessionHandler(handler_.get());
49     engine_->SetOutputHandler(handler_.get());
50     engine_->AddStanzaHandler(handler_.get());
51     engine_->SetUser(jid);
52     engine_->SetSaslHandler(
53         new buzz::PlainSaslHandler(jid, rtc::CryptString(pass), true));
54   }
55   virtual void TearDown() {
56     handler_.reset();
57     engine_.reset();
58   }
59   void RunPartialLogin(XlttStage startstage, XlttStage endstage);
60   void SetTlsOptions(buzz::TlsOptions option);
61
62  private:
63   rtc::scoped_ptr<XmppEngine> engine_;
64   rtc::scoped_ptr<XmppTestHandler> handler_;
65 };
66
67 void XmppLoginTaskTest::SetTlsOptions(buzz::TlsOptions option) {
68   engine_->SetTls(option);
69 }
70 void XmppLoginTaskTest::RunPartialLogin(XlttStage startstage,
71                                         XlttStage endstage) {
72   std::string input;
73
74   switch (startstage) {
75     case XLTT_STAGE_CONNECT: {
76       engine_->Connect();
77       XmlElement appStanza(QName("test", "app-stanza"));
78       appStanza.AddText("this-is-a-test");
79       engine_->SendStanza(&appStanza);
80
81       EXPECT_EQ("<stream:stream to=\"my-server\" xml:lang=\"*\" "
82           "version=\"1.0\" xmlns:stream=\"http://etherx.jabber.org/streams\" "
83           "xmlns=\"jabber:client\">\r\n", handler_->OutputActivity());
84       EXPECT_EQ("[OPENING]", handler_->SessionActivity());
85       EXPECT_EQ("", handler_->StanzaActivity());
86       if (endstage == XLTT_STAGE_CONNECT)
87         return;
88     }
89
90     case XLTT_STAGE_STREAMSTART: {
91       input = "<stream:stream id=\"a5f2d8c9\" version=\"1.0\" "
92           "xmlns:stream=\"http://etherx.jabber.org/streams\" "
93           "xmlns=\"jabber:client\">";
94       engine_->HandleInput(input.c_str(), input.length());
95       EXPECT_EQ("", handler_->StanzaActivity());
96       EXPECT_EQ("", handler_->SessionActivity());
97       EXPECT_EQ("", handler_->OutputActivity());
98       if (endstage == XLTT_STAGE_STREAMSTART)
99         return;
100     }
101
102     case XLTT_STAGE_TLS_FEATURES: {
103       input = "<stream:features>"
104         "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
105        "</stream:features>";
106       engine_->HandleInput(input.c_str(), input.length());
107       EXPECT_EQ("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>",
108           handler_->OutputActivity());
109       EXPECT_EQ("", handler_->StanzaActivity());
110       EXPECT_EQ("", handler_->SessionActivity());
111       if (endstage == XLTT_STAGE_TLS_FEATURES)
112         return;
113     }
114
115     case XLTT_STAGE_TLS_PROCEED: {
116       input = std::string("<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
117       engine_->HandleInput(input.c_str(), input.length());
118       EXPECT_EQ("[START-TLS my-server]"
119           "<stream:stream to=\"my-server\" xml:lang=\"*\" "
120           "version=\"1.0\" xmlns:stream=\"http://etherx.jabber.org/streams\" "
121           "xmlns=\"jabber:client\">\r\n", handler_->OutputActivity());
122       EXPECT_EQ("", handler_->StanzaActivity());
123       EXPECT_EQ("", handler_->SessionActivity());
124        if (endstage == XLTT_STAGE_TLS_PROCEED)
125         return;
126     }
127
128     case XLTT_STAGE_ENCRYPTED_START: {
129       input = std::string("<stream:stream id=\"01234567\" version=\"1.0\" "
130           "xmlns:stream=\"http://etherx.jabber.org/streams\" "
131           "xmlns=\"jabber:client\">");
132       engine_->HandleInput(input.c_str(), input.length());
133       EXPECT_EQ("", handler_->StanzaActivity());
134       EXPECT_EQ("", handler_->SessionActivity());
135       EXPECT_EQ("", handler_->OutputActivity());
136       if (endstage == XLTT_STAGE_ENCRYPTED_START)
137         return;
138     }
139
140     case XLTT_STAGE_AUTH_FEATURES: {
141       input = "<stream:features>"
142         "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"
143           "<mechanism>DIGEST-MD5</mechanism>"
144           "<mechanism>PLAIN</mechanism>"
145         "</mechanisms>"
146        "</stream:features>";
147       engine_->HandleInput(input.c_str(), input.length());
148       EXPECT_EQ("<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" "
149           "mechanism=\"PLAIN\" "
150           "auth:allow-non-google-login=\"true\" "
151           "auth:client-uses-full-bind-result=\"true\" "
152           "xmlns:auth=\"http://www.google.com/talk/protocol/auth\""
153           ">AGRhdmlkAGRhdmlk</auth>",
154           handler_->OutputActivity());
155       EXPECT_EQ("", handler_->StanzaActivity());
156       EXPECT_EQ("", handler_->SessionActivity());
157        if (endstage == XLTT_STAGE_AUTH_FEATURES)
158         return;
159     }
160
161     case XLTT_STAGE_AUTH_SUCCESS: {
162       input = "<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>";
163       engine_->HandleInput(input.c_str(), input.length());
164       EXPECT_EQ("<stream:stream to=\"my-server\" xml:lang=\"*\" "
165           "version=\"1.0\" xmlns:stream=\"http://etherx.jabber.org/streams\" "
166           "xmlns=\"jabber:client\">\r\n", handler_->OutputActivity());
167       EXPECT_EQ("", handler_->StanzaActivity());
168       EXPECT_EQ("", handler_->SessionActivity());
169        if (endstage == XLTT_STAGE_AUTH_SUCCESS)
170         return;
171     }
172
173     case XLTT_STAGE_AUTHENTICATED_START: {
174       input = std::string("<stream:stream id=\"01234567\" version=\"1.0\" "
175           "xmlns:stream=\"http://etherx.jabber.org/streams\" "
176           "xmlns=\"jabber:client\">");
177       engine_->HandleInput(input.c_str(), input.length());
178       EXPECT_EQ("", handler_->StanzaActivity());
179       EXPECT_EQ("", handler_->SessionActivity());
180       EXPECT_EQ("", handler_->OutputActivity());
181       if (endstage == XLTT_STAGE_AUTHENTICATED_START)
182         return;
183     }
184
185     case XLTT_STAGE_BIND_FEATURES: {
186       input = "<stream:features>"
187           "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>"
188           "<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>"
189         "</stream:features>";
190       engine_->HandleInput(input.c_str(), input.length());
191       EXPECT_EQ("<iq type=\"set\" id=\"0\">"
192           "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/></iq>",
193           handler_->OutputActivity());
194       EXPECT_EQ("", handler_->StanzaActivity());
195       EXPECT_EQ("", handler_->SessionActivity());
196       if (endstage == XLTT_STAGE_BIND_FEATURES)
197         return;
198     }
199
200     case XLTT_STAGE_BIND_SUCCESS: {
201       input = "<iq type='result' id='0'>"
202           "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>"
203           "<jid>david@my-server/test</jid></bind></iq>";
204       engine_->HandleInput(input.c_str(), input.length());
205       EXPECT_EQ("<iq type=\"set\" id=\"1\">"
206           "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/></iq>",
207           handler_->OutputActivity());
208       EXPECT_EQ("", handler_->StanzaActivity());
209       EXPECT_EQ("", handler_->SessionActivity());
210       if (endstage == XLTT_STAGE_BIND_SUCCESS)
211         return;
212     }
213
214     case XLTT_STAGE_SESSION_SUCCESS: {
215       input = "<iq type='result' id='1'/>";
216       engine_->HandleInput(input.c_str(), input.length());
217       EXPECT_EQ("<test:app-stanza xmlns:test=\"test\">this-is-a-test"
218           "</test:app-stanza>", handler_->OutputActivity());
219       EXPECT_EQ("[OPEN]", handler_->SessionActivity());
220       EXPECT_EQ("", handler_->StanzaActivity());
221       if (endstage == XLTT_STAGE_SESSION_SUCCESS)
222         return;
223     }
224   }
225 }
226
227 TEST_F(XmppLoginTaskTest, TestUtf8Good) {
228   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_CONNECT);
229
230   std::string input = "<?xml version='1.0' encoding='UTF-8'?>"
231       "<stream:stream id=\"a5f2d8c9\" version=\"1.0\" "
232       "xmlns:stream=\"http://etherx.jabber.org/streams\" "
233       "xmlns=\"jabber:client\">";
234   engine()->HandleInput(input.c_str(), input.length());
235   EXPECT_EQ("", handler()->OutputActivity());
236   EXPECT_EQ("", handler()->SessionActivity());
237   EXPECT_EQ("", handler()->StanzaActivity());
238 }
239
240 TEST_F(XmppLoginTaskTest, TestNonUtf8Bad) {
241   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_CONNECT);
242
243   std::string input = "<?xml version='1.0' encoding='ISO-8859-1'?>"
244       "<stream:stream id=\"a5f2d8c9\" version=\"1.0\" "
245       "xmlns:stream=\"http://etherx.jabber.org/streams\" "
246       "xmlns=\"jabber:client\">";
247   engine()->HandleInput(input.c_str(), input.length());
248   EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
249   EXPECT_EQ("[CLOSED][ERROR-XML]", handler()->SessionActivity());
250   EXPECT_EQ("", handler()->StanzaActivity());
251 }
252
253 TEST_F(XmppLoginTaskTest, TestNoFeatures) {
254   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_STREAMSTART);
255
256   std::string input = "<iq type='get' id='1'/>";
257   engine()->HandleInput(input.c_str(), input.length());
258
259   EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
260   EXPECT_EQ("[CLOSED][ERROR-VERSION]", handler()->SessionActivity());
261   EXPECT_EQ("", handler()->StanzaActivity());
262 }
263
264 TEST_F(XmppLoginTaskTest, TestTlsRequiredNotPresent) {
265   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_STREAMSTART);
266
267   std::string input = "<stream:features>"
268       "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"
269         "<mechanism>DIGEST-MD5</mechanism>"
270         "<mechanism>PLAIN</mechanism>"
271       "</mechanisms>"
272      "</stream:features>";
273   engine()->HandleInput(input.c_str(), input.length());
274
275   EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
276   EXPECT_EQ("[CLOSED][ERROR-TLS]", handler()->SessionActivity());
277   EXPECT_EQ("", handler()->StanzaActivity());
278 }
279
280 TEST_F(XmppLoginTaskTest, TestTlsRequeiredAndPresent) {
281   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_STREAMSTART);
282
283   std::string input = "<stream:features>"
284       "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>"
285         "<required/>"
286       "</starttls>"
287       "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"
288         "<mechanism>X-GOOGLE-TOKEN</mechanism>"
289         "<mechanism>PLAIN</mechanism>"
290         "<mechanism>X-OAUTH2</mechanism>"
291       "</mechanisms>"
292      "</stream:features>";
293   engine()->HandleInput(input.c_str(), input.length());
294
295   EXPECT_EQ("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>",
296       handler()->OutputActivity());
297   EXPECT_EQ("", handler()->SessionActivity());
298   EXPECT_EQ("", handler()->StanzaActivity());
299 }
300
301 TEST_F(XmppLoginTaskTest, TestTlsEnabledNotPresent) {
302   SetTlsOptions(buzz::TLS_ENABLED);
303   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_STREAMSTART);
304
305   std::string input = "<stream:features>"
306       "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"
307         "<mechanism>DIGEST-MD5</mechanism>"
308         "<mechanism>PLAIN</mechanism>"
309       "</mechanisms>"
310      "</stream:features>";
311   engine()->HandleInput(input.c_str(), input.length());
312
313   EXPECT_EQ("<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" "
314       "mechanism=\"PLAIN\" auth:allow-non-google-login=\"true\" "
315       "auth:client-uses-full-bind-result=\"true\" "
316       "xmlns:auth=\"http://www.google.com/talk/protocol/auth\""
317       ">AGRhdmlkAGRhdmlk</auth>", handler()->OutputActivity());
318   EXPECT_EQ("", handler()->SessionActivity());
319   EXPECT_EQ("", handler()->StanzaActivity());
320 }
321
322 TEST_F(XmppLoginTaskTest, TestTlsEnabledAndPresent) {
323   SetTlsOptions(buzz::TLS_ENABLED);
324   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_STREAMSTART);
325
326   std::string input = "<stream:features>"
327       "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"
328         "<mechanism>X-GOOGLE-TOKEN</mechanism>"
329         "<mechanism>PLAIN</mechanism>"
330         "<mechanism>X-OAUTH2</mechanism>"
331       "</mechanisms>"
332       "</stream:features>";
333   engine()->HandleInput(input.c_str(), input.length());
334
335   EXPECT_EQ("<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" "
336       "mechanism=\"PLAIN\" auth:allow-non-google-login=\"true\" "
337       "auth:client-uses-full-bind-result=\"true\" "
338       "xmlns:auth=\"http://www.google.com/talk/protocol/auth\""
339       ">AGRhdmlkAGRhdmlk</auth>", handler()->OutputActivity());
340   EXPECT_EQ("", handler()->SessionActivity());
341   EXPECT_EQ("", handler()->StanzaActivity());
342 }
343
344 TEST_F(XmppLoginTaskTest, TestTlsDisabledNotPresent) {
345   SetTlsOptions(buzz::TLS_DISABLED);
346   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_STREAMSTART);
347
348     std::string input = "<stream:features>"
349       "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"
350         "<mechanism>DIGEST-MD5</mechanism>"
351         "<mechanism>PLAIN</mechanism>"
352       "</mechanisms>"
353      "</stream:features>";
354   engine()->HandleInput(input.c_str(), input.length());
355
356   EXPECT_EQ("<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" "
357       "mechanism=\"PLAIN\" auth:allow-non-google-login=\"true\" "
358       "auth:client-uses-full-bind-result=\"true\" "
359       "xmlns:auth=\"http://www.google.com/talk/protocol/auth\""
360       ">AGRhdmlkAGRhdmlk</auth>", handler()->OutputActivity());
361   EXPECT_EQ("", handler()->SessionActivity());
362   EXPECT_EQ("", handler()->StanzaActivity());
363 }
364
365 TEST_F(XmppLoginTaskTest, TestTlsDisabledAndPresent) {
366   SetTlsOptions(buzz::TLS_DISABLED);
367   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_STREAMSTART);
368
369   std::string input = "<stream:features>"
370       "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"
371         "<mechanism>X-GOOGLE-TOKEN</mechanism>"
372         "<mechanism>PLAIN</mechanism>"
373         "<mechanism>X-OAUTH2</mechanism>"
374       "</mechanisms>"
375       "</stream:features>";
376   engine()->HandleInput(input.c_str(), input.length());
377
378   EXPECT_EQ("<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" "
379       "mechanism=\"PLAIN\" auth:allow-non-google-login=\"true\" "
380       "auth:client-uses-full-bind-result=\"true\" "
381       "xmlns:auth=\"http://www.google.com/talk/protocol/auth\""
382       ">AGRhdmlkAGRhdmlk</auth>", handler()->OutputActivity());
383   EXPECT_EQ("", handler()->SessionActivity());
384   EXPECT_EQ("", handler()->StanzaActivity());
385 }
386
387 TEST_F(XmppLoginTaskTest, TestTlsFailure) {
388   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_TLS_FEATURES);
389
390   std::string input = "<failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>";
391   engine()->HandleInput(input.c_str(), input.length());
392
393   EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
394   EXPECT_EQ("[CLOSED][ERROR-TLS]", handler()->SessionActivity());
395   EXPECT_EQ("", handler()->StanzaActivity());
396 }
397
398 TEST_F(XmppLoginTaskTest, TestTlsBadStream) {
399   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_TLS_PROCEED);
400
401   std::string input = "<wrongtag>";
402   engine()->HandleInput(input.c_str(), input.length());
403
404   EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
405   EXPECT_EQ("[CLOSED][ERROR-VERSION]", handler()->SessionActivity());
406   EXPECT_EQ("", handler()->StanzaActivity());
407 }
408
409 TEST_F(XmppLoginTaskTest, TestMissingSaslPlain) {
410   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_ENCRYPTED_START);
411
412   std::string input = "<stream:features>"
413         "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"
414           "<mechanism>DIGEST-MD5</mechanism>"
415         "</mechanisms>"
416        "</stream:features>";
417   engine()->HandleInput(input.c_str(), input.length());
418
419   EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
420   EXPECT_EQ("[CLOSED][ERROR-AUTH]", handler()->SessionActivity());
421   EXPECT_EQ("", handler()->StanzaActivity());
422 }
423
424 TEST_F(XmppLoginTaskTest, TestWrongPassword) {
425   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_AUTH_FEATURES);
426
427   std::string input = "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>";
428   engine()->HandleInput(input.c_str(), input.length());
429
430   EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
431   EXPECT_EQ("[CLOSED][ERROR-UNAUTHORIZED]", handler()->SessionActivity());
432   EXPECT_EQ("", handler()->StanzaActivity());
433 }
434
435 TEST_F(XmppLoginTaskTest, TestAuthBadStream) {
436   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_AUTH_SUCCESS);
437
438   std::string input = "<wrongtag>";
439   engine()->HandleInput(input.c_str(), input.length());
440
441   EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
442   EXPECT_EQ("[CLOSED][ERROR-VERSION]", handler()->SessionActivity());
443   EXPECT_EQ("", handler()->StanzaActivity());
444 }
445
446 TEST_F(XmppLoginTaskTest, TestMissingBindFeature) {
447   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_AUTHENTICATED_START);
448
449   std::string input = "<stream:features>"
450           "<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>"
451         "</stream:features>";
452   engine()->HandleInput(input.c_str(), input.length());
453
454   EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
455   EXPECT_EQ("[CLOSED][ERROR-BIND]", handler()->SessionActivity());
456 }
457
458 TEST_F(XmppLoginTaskTest, TestMissingSessionFeature) {
459   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_AUTHENTICATED_START);
460
461   std::string input = "<stream:features>"
462           "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>"
463         "</stream:features>";
464   engine()->HandleInput(input.c_str(), input.length());
465
466   EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
467   EXPECT_EQ("[CLOSED][ERROR-BIND]", handler()->SessionActivity());
468   EXPECT_EQ("", handler()->StanzaActivity());
469 }
470
471 /* TODO: Handle this case properly inside XmppLoginTask.
472 TEST_F(XmppLoginTaskTest, TestBindFailure1) {
473   // check wrong JID
474   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_BIND_FEATURES);
475
476   std::string input = "<iq type='result' id='0'>"
477       "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>"
478       "<jid>davey@my-server/test</jid></bind></iq>";
479   engine()->HandleInput(input.c_str(), input.length());
480
481   EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
482   EXPECT_EQ("[CLOSED][ERROR-BIND]", handler()->SessionActivity());
483   EXPECT_EQ("", handler()->StanzaActivity());
484 }
485 */
486
487 TEST_F(XmppLoginTaskTest, TestBindFailure2) {
488   // check missing JID
489   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_BIND_FEATURES);
490
491   std::string input = "<iq type='result' id='0'>"
492       "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/></iq>";
493   engine()->HandleInput(input.c_str(), input.length());
494
495   EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
496   EXPECT_EQ("[CLOSED][ERROR-BIND]", handler()->SessionActivity());
497   EXPECT_EQ("", handler()->StanzaActivity());
498 }
499
500 TEST_F(XmppLoginTaskTest, TestBindFailure3) {
501   // check plain failure
502   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_BIND_FEATURES);
503
504   std::string input = "<iq type='error' id='0'/>";
505   engine()->HandleInput(input.c_str(), input.length());
506
507   EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
508   EXPECT_EQ("[CLOSED][ERROR-BIND]", handler()->SessionActivity());
509   EXPECT_EQ("", handler()->StanzaActivity());
510 }
511
512 TEST_F(XmppLoginTaskTest, TestBindFailure4) {
513   // check wrong id to ignore
514   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_BIND_FEATURES);
515
516   std::string input = "<iq type='error' id='1'/>";
517   engine()->HandleInput(input.c_str(), input.length());
518
519   // continue after an ignored iq
520   RunPartialLogin(XLTT_STAGE_BIND_SUCCESS, XLTT_STAGE_SESSION_SUCCESS);
521 }
522
523 TEST_F(XmppLoginTaskTest, TestSessionFailurePlain1) {
524   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_BIND_SUCCESS);
525
526   std::string input = "<iq type='error' id='1'/>";
527   engine()->HandleInput(input.c_str(), input.length());
528
529   EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
530   EXPECT_EQ("[CLOSED][ERROR-BIND]", handler()->SessionActivity());
531 }
532
533 TEST_F(XmppLoginTaskTest, TestSessionFailurePlain2) {
534   RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_BIND_SUCCESS);
535
536   // check reverse iq to ignore
537   // TODO: consider queueing or passing through?
538   std::string input = "<iq type='get' id='1'/>";
539   engine()->HandleInput(input.c_str(), input.length());
540
541   EXPECT_EQ("", handler()->OutputActivity());
542   EXPECT_EQ("", handler()->SessionActivity());
543
544   // continue after an ignored iq
545   RunPartialLogin(XLTT_STAGE_SESSION_SUCCESS, XLTT_STAGE_SESSION_SUCCESS);
546 }
547
548 TEST_F(XmppLoginTaskTest, TestBadXml) {
549   int errorKind = 0;
550   for (XlttStage stage = XLTT_STAGE_CONNECT;
551       stage <= XLTT_STAGE_SESSION_SUCCESS;
552       stage = static_cast<XlttStage>(stage + 1)) {
553     RunPartialLogin(XLTT_STAGE_CONNECT, stage);
554
555     std::string input;
556     switch (errorKind++ % 5) {
557       case 0: input = "&syntax;"; break;
558       case 1: input = "<nons:iq/>"; break;
559       case 2: input = "<iq a='b' a='dupe'/>"; break;
560       case 3: input = "<>"; break;
561       case 4: input = "<iq a='<wrong>'>"; break;
562     }
563
564     engine()->HandleInput(input.c_str(), input.length());
565
566     EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
567     EXPECT_EQ("[CLOSED][ERROR-XML]", handler()->SessionActivity());
568
569     TearDown();
570     SetUp();
571   }
572 }
573
574 TEST_F(XmppLoginTaskTest, TestStreamError) {
575   for (XlttStage stage = XLTT_STAGE_CONNECT;
576       stage <= XLTT_STAGE_SESSION_SUCCESS;
577       stage = static_cast<XlttStage>(stage + 1)) {
578     switch (stage) {
579       case XLTT_STAGE_CONNECT:
580       case XLTT_STAGE_TLS_PROCEED:
581       case XLTT_STAGE_AUTH_SUCCESS:
582         continue;
583       default:
584         break;
585     }
586
587     RunPartialLogin(XLTT_STAGE_CONNECT, stage);
588
589     std::string input = "<stream:error>"
590         "<xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>"
591         "<text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-streams'>"
592         "Some special application diagnostic information!"
593         "</text>"
594         "<escape-your-data xmlns='application-ns'/>"
595         "</stream:error>";
596
597     engine()->HandleInput(input.c_str(), input.length());
598
599     EXPECT_EQ("[CLOSED]", handler()->OutputActivity());
600     EXPECT_EQ("[CLOSED][ERROR-STREAM]", handler()->SessionActivity());
601
602     EXPECT_EQ("<str:error xmlns:str=\"http://etherx.jabber.org/streams\">"
603         "<xml-not-well-formed xmlns=\"urn:ietf:params:xml:ns:xmpp-streams\"/>"
604         "<text xml:lang=\"en\" xmlns=\"urn:ietf:params:xml:ns:xmpp-streams\">"
605         "Some special application diagnostic information!"
606         "</text>"
607         "<escape-your-data xmlns=\"application-ns\"/>"
608         "</str:error>", engine()->GetStreamError()->Str());
609
610     TearDown();
611     SetUp();
612   }
613 }
614