Home | History | Annotate | Download | only in xmpp
      1 /*
      2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include <iostream>
     12 #include <sstream>
     13 #include <string>
     14 #include "buzz/chatroommodule.h"
     15 #include "buzz/constants.h"
     16 #include "buzz/xmlelement.h"
     17 #include "buzz/xmppengine.h"
     18 #include "common/common.h"
     19 #include "engine/util_unittest.h"
     20 #include "test/unittest-inl.h"
     21 #include "test/unittest.h"
     22 
     23 #define TEST_OK(x) TEST_EQ((x),XMPP_RETURN_OK)
     24 #define TEST_BADARGUMENT(x) TEST_EQ((x),XMPP_RETURN_BADARGUMENT)
     25 
     26 namespace buzz {
     27 
     28 class MultiUserChatModuleTest;
     29 
     30 static void
     31 WriteEnteredStatus(std::ostream& os, XmppChatroomEnteredStatus status) {
     32   switch(status) {
     33     case XMPP_CHATROOM_ENTERED_SUCCESS:
     34       os<<"success";
     35       break;
     36     case XMPP_CHATROOM_ENTERED_FAILURE_NICKNAME_CONFLICT:
     37       os<<"failure(nickname conflict)";
     38       break;
     39     case XMPP_CHATROOM_ENTERED_FAILURE_PASSWORD_REQUIRED:
     40       os<<"failure(password required)";
     41       break;
     42     case XMPP_CHATROOM_ENTERED_FAILURE_PASSWORD_INCORRECT:
     43       os<<"failure(password incorrect)";
     44       break;
     45     case XMPP_CHATROOM_ENTERED_FAILURE_NOT_A_MEMBER:
     46       os<<"failure(not a member)";
     47       break;
     48     case XMPP_CHATROOM_ENTERED_FAILURE_MEMBER_BANNED:
     49       os<<"failure(member banned)";
     50       break;
     51     case XMPP_CHATROOM_ENTERED_FAILURE_MAX_USERS:
     52       os<<"failure(max users)";
     53       break;
     54     case XMPP_CHATROOM_ENTERED_FAILURE_ROOM_LOCKED:
     55       os<<"failure(room locked)";
     56       break;
     57     case XMPP_CHATROOM_ENTERED_FAILURE_UNSPECIFIED:
     58       os<<"failure(unspecified)";
     59       break;
     60     default:
     61       os<<"unknown";
     62       break;
     63   }
     64 }
     65 
     66 static void
     67 WriteExitedStatus(std::ostream& os, XmppChatroomExitedStatus status) {
     68   switch (status) {
     69     case XMPP_CHATROOM_EXITED_REQUESTED:
     70       os<<"requested";
     71       break;
     72     case XMPP_CHATROOM_EXITED_BANNED:
     73       os<<"banned";
     74       break;
     75     case XMPP_CHATROOM_EXITED_KICKED:
     76       os<<"kicked";
     77       break;
     78     case XMPP_CHATROOM_EXITED_NOT_A_MEMBER:
     79       os<<"not member";
     80       break;
     81     case XMPP_CHATROOM_EXITED_SYSTEM_SHUTDOWN:
     82       os<<"system shutdown";
     83       break;
     84     case XMPP_CHATROOM_EXITED_UNSPECIFIED:
     85       os<<"unspecified";
     86       break;
     87     default:
     88       os<<"unknown";
     89       break;
     90   }
     91 }
     92 
     93 //! This session handler saves all calls to a string.  These are events and
     94 //! data delivered form the engine to application code.
     95 class XmppTestChatroomHandler : public XmppChatroomHandler {
     96 public:
     97   XmppTestChatroomHandler() {}
     98   virtual ~XmppTestChatroomHandler() {}
     99 
    100   void ChatroomEnteredStatus(XmppChatroomModule* room,
    101                              XmppChatroomEnteredStatus status) {
    102     RTC_UNUSED(room);
    103     ss_ <<"[ChatroomEnteredStatus status: ";
    104     WriteEnteredStatus(ss_, status);
    105     ss_ <<"]";
    106   }
    107 
    108 
    109   void ChatroomExitedStatus(XmppChatroomModule* room,
    110                             XmppChatroomExitedStatus status) {
    111     RTC_UNUSED(room);
    112     ss_ <<"[ChatroomExitedStatus status: ";
    113     WriteExitedStatus(ss_, status);
    114     ss_ <<"]";
    115   }
    116 
    117   void MemberEntered(XmppChatroomModule* room,
    118                           const XmppChatroomMember* entered_member) {
    119     RTC_UNUSED(room);
    120     ss_ << "[MemberEntered " << entered_member->member_jid().Str() << "]";
    121   }
    122 
    123   void MemberExited(XmppChatroomModule* room,
    124                          const XmppChatroomMember* exited_member) {
    125     RTC_UNUSED(room);
    126     ss_ << "[MemberExited " << exited_member->member_jid().Str() << "]";
    127   }
    128 
    129   void MemberChanged(XmppChatroomModule* room,
    130       const XmppChatroomMember* changed_member) {
    131     RTC_UNUSED(room);
    132     ss_ << "[MemberChanged " << changed_member->member_jid().Str() << "]";
    133   }
    134 
    135   virtual void MessageReceived(XmppChatroomModule* room, const XmlElement& message) {
    136     RTC_UNUSED2(room, message);
    137   }
    138 
    139 
    140   std::string Str() {
    141     return ss_.str();
    142   }
    143 
    144   std::string StrClear() {
    145     std::string result = ss_.str();
    146     ss_.str("");
    147     return result;
    148   }
    149 
    150 private:
    151   std::stringstream ss_;
    152 };
    153 
    154 //! This is the class that holds all of the unit test code for the
    155 //! roster module
    156 class XmppChatroomModuleTest : public UnitTest {
    157 public:
    158   XmppChatroomModuleTest() {}
    159 
    160   void TestEnterExitChatroom() {
    161     std::stringstream dump;
    162 
    163     // Configure the engine
    164     rtc::scoped_ptr<XmppEngine> engine(XmppEngine::Create());
    165     XmppTestHandler handler(engine.get());
    166 
    167     // Configure the module and handler
    168     rtc::scoped_ptr<XmppChatroomModule> chatroom(XmppChatroomModule::Create());
    169 
    170     // Configure the module handler
    171     chatroom->RegisterEngine(engine.get());
    172 
    173     // Set up callbacks
    174     engine->SetOutputHandler(&handler);
    175     engine->AddStanzaHandler(&handler);
    176     engine->SetSessionHandler(&handler);
    177 
    178     // Set up minimal login info
    179     engine->SetUser(Jid("david@my-server"));
    180     engine->SetPassword("david");
    181 
    182     // Do the whole login handshake
    183     RunLogin(this, engine.get(), &handler);
    184     TEST_EQ("", handler.OutputActivity());
    185 
    186     // Get the chatroom and set the handler
    187     XmppTestChatroomHandler chatroom_handler;
    188     chatroom->set_chatroom_handler(static_cast<XmppChatroomHandler*>(&chatroom_handler));
    189 
    190     // try to enter the chatroom
    191     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_NOT_IN_ROOM);
    192     chatroom->set_nickname("thirdwitch");
    193     chatroom->set_chatroom_jid(Jid("darkcave@my-server"));
    194     chatroom->RequestEnterChatroom("", XMPP_CONNECTION_STATUS_UNKNOWN, "en");
    195     TEST_EQ(chatroom_handler.StrClear(), "");
    196     TEST_EQ(handler.OutputActivity(),
    197       "<presence to=\"darkcave@my-server/thirdwitch\">"
    198         "<muc:x xmlns:muc=\"http://jabber.org/protocol/muc\"/>"
    199       "</presence>");
    200     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_REQUESTED_ENTER);
    201 
    202     // simulate the server and test the client
    203     std::string input;
    204     input = "<presence from=\"darkcave@my-server/firstwitch\" to=\"david@my-server\">"
    205              "<x xmlns=\"http://jabber.org/protocol/muc#user\">"
    206               "<item affiliation=\"owner\" role=\"participant\"/>"
    207              "</x>"
    208             "</presence>";
    209     TEST_OK(engine->HandleInput(input.c_str(), input.length()));
    210     TEST_EQ(chatroom_handler.StrClear(), "");
    211     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_REQUESTED_ENTER);
    212 
    213     input = "<presence from=\"darkcave@my-server/secondwitch\" to=\"david@my-server\">"
    214              "<x xmlns=\"http://jabber.org/protocol/muc#user\">"
    215               "<item affiliation=\"member\" role=\"participant\"/>"
    216              "</x>"
    217             "</presence>";
    218     TEST_OK(engine->HandleInput(input.c_str(), input.length()));
    219     TEST_EQ(chatroom_handler.StrClear(), "");
    220     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_REQUESTED_ENTER);
    221 
    222     input = "<presence from=\"darkcave@my-server/thirdwitch\" to=\"david@my-server\">"
    223              "<x xmlns=\"http://jabber.org/protocol/muc#user\">"
    224               "<item affiliation=\"member\" role=\"participant\"/>"
    225              "</x>"
    226             "</presence>";
    227     TEST_OK(engine->HandleInput(input.c_str(), input.length()));
    228     TEST_EQ(chatroom_handler.StrClear(),
    229       "[ChatroomEnteredStatus status: success]");
    230     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_IN_ROOM);
    231 
    232     // simulate somebody else entering the room after we entered
    233     input = "<presence from=\"darkcave@my-server/fourthwitch\" to=\"david@my-server\">"
    234              "<x xmlns=\"http://jabber.org/protocol/muc#user\">"
    235               "<item affiliation=\"member\" role=\"participant\"/>"
    236              "</x>"
    237             "</presence>";
    238     TEST_OK(engine->HandleInput(input.c_str(), input.length()));
    239     TEST_EQ(chatroom_handler.StrClear(), "[MemberEntered darkcave@my-server/fourthwitch]");
    240     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_IN_ROOM);
    241 
    242     // simulate somebody else leaving the room after we entered
    243     input = "<presence from=\"darkcave@my-server/secondwitch\" to=\"david@my-server\" type=\"unavailable\">"
    244              "<x xmlns=\"http://jabber.org/protocol/muc#user\">"
    245               "<item affiliation=\"member\" role=\"participant\"/>"
    246              "</x>"
    247             "</presence>";
    248     TEST_OK(engine->HandleInput(input.c_str(), input.length()));
    249     TEST_EQ(chatroom_handler.StrClear(), "[MemberExited darkcave@my-server/secondwitch]");
    250     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_IN_ROOM);
    251 
    252     // try to leave the room
    253     chatroom->RequestExitChatroom();
    254     TEST_EQ(chatroom_handler.StrClear(), "");
    255     TEST_EQ(handler.OutputActivity(),
    256       "<presence to=\"darkcave@my-server/thirdwitch\" type=\"unavailable\"/>");
    257     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_REQUESTED_EXIT);
    258 
    259     // simulate the server and test the client
    260     input = "<presence from=\"darkcave@my-server/thirdwitch\" to=\"david@my-server\" type=\"unavailable\">"
    261              "<x xmlns=\"http://jabber.org/protocol/muc#user\">"
    262               "<item affiliation=\"member\" role=\"participant\"/>"
    263              "</x>"
    264             "</presence>";
    265     TEST_OK(engine->HandleInput(input.c_str(), input.length()));
    266     TEST_EQ(chatroom_handler.StrClear(),
    267       "[ChatroomExitedStatus status: requested]");
    268     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_NOT_IN_ROOM);
    269   }
    270 
    271 };
    272 
    273 // A global function that creates the test suite for this set of tests.
    274 TestBase* ChatroomModuleTest_Create() {
    275   TestSuite* suite = new TestSuite("ChatroomModuleTest");
    276   ADD_TEST(suite, XmppChatroomModuleTest, TestEnterExitChatroom);
    277   return suite;
    278 }
    279 
    280 }
    281