Home | History | Annotate | Download | only in xmpp
      1 /*
      2  * libjingle
      3  * Copyright 2004, Google Inc.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *  1. Redistributions of source code must retain the above copyright notice,
      9  *     this list of conditions and the following disclaimer.
     10  *  2. Redistributions in binary form must reproduce the above copyright notice,
     11  *     this list of conditions and the following disclaimer in the documentation
     12  *     and/or other materials provided with the distribution.
     13  *  3. The name of the author may not be used to endorse or promote products
     14  *     derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include <string>
     29 #include <sstream>
     30 #include <iostream>
     31 #include "common/common.h"
     32 #include "buzz/xmppengine.h"
     33 #include "buzz/xmlelement.h"
     34 #include "buzz/chatroommodule.h"
     35 #include "buzz/constants.h"
     36 #include "engine/util_unittest.h"
     37 #include "test/unittest.h"
     38 #include "test/unittest-inl.h"
     39 
     40 #define TEST_OK(x) TEST_EQ((x),XMPP_RETURN_OK)
     41 #define TEST_BADARGUMENT(x) TEST_EQ((x),XMPP_RETURN_BADARGUMENT)
     42 
     43 namespace buzz {
     44 
     45 class MultiUserChatModuleTest;
     46 
     47 static void
     48 WriteEnteredStatus(std::ostream& os, XmppChatroomEnteredStatus status) {
     49   switch(status) {
     50     case XMPP_CHATROOM_ENTERED_SUCCESS:
     51       os<<"success";
     52       break;
     53     case XMPP_CHATROOM_ENTERED_FAILURE_NICKNAME_CONFLICT:
     54       os<<"failure(nickname conflict)";
     55       break;
     56     case XMPP_CHATROOM_ENTERED_FAILURE_PASSWORD_REQUIRED:
     57       os<<"failure(password required)";
     58       break;
     59     case XMPP_CHATROOM_ENTERED_FAILURE_PASSWORD_INCORRECT:
     60       os<<"failure(password incorrect)";
     61       break;
     62     case XMPP_CHATROOM_ENTERED_FAILURE_NOT_A_MEMBER:
     63       os<<"failure(not a member)";
     64       break;
     65     case XMPP_CHATROOM_ENTERED_FAILURE_MEMBER_BANNED:
     66       os<<"failure(member banned)";
     67       break;
     68     case XMPP_CHATROOM_ENTERED_FAILURE_MAX_USERS:
     69       os<<"failure(max users)";
     70       break;
     71     case XMPP_CHATROOM_ENTERED_FAILURE_ROOM_LOCKED:
     72       os<<"failure(room locked)";
     73       break;
     74     case XMPP_CHATROOM_ENTERED_FAILURE_UNSPECIFIED:
     75       os<<"failure(unspecified)";
     76       break;
     77     default:
     78       os<<"unknown";
     79       break;
     80   }
     81 }
     82 
     83 static void
     84 WriteExitedStatus(std::ostream& os, XmppChatroomExitedStatus status) {
     85   switch (status) {
     86     case XMPP_CHATROOM_EXITED_REQUESTED:
     87       os<<"requested";
     88       break;
     89     case XMPP_CHATROOM_EXITED_BANNED:
     90       os<<"banned";
     91       break;
     92     case XMPP_CHATROOM_EXITED_KICKED:
     93       os<<"kicked";
     94       break;
     95     case XMPP_CHATROOM_EXITED_NOT_A_MEMBER:
     96       os<<"not member";
     97       break;
     98     case XMPP_CHATROOM_EXITED_SYSTEM_SHUTDOWN:
     99       os<<"system shutdown";
    100       break;
    101     case XMPP_CHATROOM_EXITED_UNSPECIFIED:
    102       os<<"unspecified";
    103       break;
    104     default:
    105       os<<"unknown";
    106       break;
    107   }
    108 }
    109 
    110 //! This session handler saves all calls to a string.  These are events and
    111 //! data delivered form the engine to application code.
    112 class XmppTestChatroomHandler : public XmppChatroomHandler {
    113 public:
    114   XmppTestChatroomHandler() {}
    115   virtual ~XmppTestChatroomHandler() {}
    116 
    117   void ChatroomEnteredStatus(XmppChatroomModule* room,
    118                              XmppChatroomEnteredStatus status) {
    119     UNUSED(room);
    120     ss_ <<"[ChatroomEnteredStatus status: ";
    121     WriteEnteredStatus(ss_, status);
    122     ss_ <<"]";
    123   }
    124 
    125 
    126   void ChatroomExitedStatus(XmppChatroomModule* room,
    127                             XmppChatroomExitedStatus status) {
    128     UNUSED(room);
    129     ss_ <<"[ChatroomExitedStatus status: ";
    130     WriteExitedStatus(ss_, status);
    131     ss_ <<"]";
    132   }
    133 
    134   void MemberEntered(XmppChatroomModule* room,
    135                           const XmppChatroomMember* entered_member) {
    136     UNUSED(room);
    137     ss_ << "[MemberEntered " << entered_member->member_jid().Str() << "]";
    138   }
    139 
    140   void MemberExited(XmppChatroomModule* room,
    141                          const XmppChatroomMember* exited_member) {
    142     UNUSED(room);
    143     ss_ << "[MemberExited " << exited_member->member_jid().Str() << "]";
    144   }
    145 
    146   void MemberChanged(XmppChatroomModule* room,
    147       const XmppChatroomMember* changed_member) {
    148     UNUSED(room);
    149     ss_ << "[MemberChanged " << changed_member->member_jid().Str() << "]";
    150   }
    151 
    152   virtual void MessageReceived(XmppChatroomModule* room, const XmlElement& message) {
    153     UNUSED2(room, message);
    154   }
    155 
    156 
    157   std::string Str() {
    158     return ss_.str();
    159   }
    160 
    161   std::string StrClear() {
    162     std::string result = ss_.str();
    163     ss_.str("");
    164     return result;
    165   }
    166 
    167 private:
    168   std::stringstream ss_;
    169 };
    170 
    171 //! This is the class that holds all of the unit test code for the
    172 //! roster module
    173 class XmppChatroomModuleTest : public UnitTest {
    174 public:
    175   XmppChatroomModuleTest() {}
    176 
    177   void TestEnterExitChatroom() {
    178     std::stringstream dump;
    179 
    180     // Configure the engine
    181     scoped_ptr<XmppEngine> engine(XmppEngine::Create());
    182     XmppTestHandler handler(engine.get());
    183 
    184     // Configure the module and handler
    185     scoped_ptr<XmppChatroomModule> chatroom(XmppChatroomModule::Create());
    186 
    187     // Configure the module handler
    188     chatroom->RegisterEngine(engine.get());
    189 
    190     // Set up callbacks
    191     engine->SetOutputHandler(&handler);
    192     engine->AddStanzaHandler(&handler);
    193     engine->SetSessionHandler(&handler);
    194 
    195     // Set up minimal login info
    196     engine->SetUser(Jid("david@my-server"));
    197     engine->SetPassword("david");
    198 
    199     // Do the whole login handshake
    200     RunLogin(this, engine.get(), &handler);
    201     TEST_EQ("", handler.OutputActivity());
    202 
    203     // Get the chatroom and set the handler
    204     XmppTestChatroomHandler chatroom_handler;
    205     chatroom->set_chatroom_handler(static_cast<XmppChatroomHandler*>(&chatroom_handler));
    206 
    207     // try to enter the chatroom
    208     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_NOT_IN_ROOM);
    209     chatroom->set_nickname("thirdwitch");
    210     chatroom->set_chatroom_jid(Jid("darkcave@my-server"));
    211     chatroom->RequestEnterChatroom("", XMPP_CONNECTION_STATUS_UNKNOWN, "en");
    212     TEST_EQ(chatroom_handler.StrClear(), "");
    213     TEST_EQ(handler.OutputActivity(),
    214       "<presence to=\"darkcave@my-server/thirdwitch\">"
    215         "<muc:x xmlns:muc=\"http://jabber.org/protocol/muc\"/>"
    216       "</presence>");
    217     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_REQUESTED_ENTER);
    218 
    219     // simulate the server and test the client
    220     std::string input;
    221     input = "<presence from=\"darkcave@my-server/firstwitch\" to=\"david@my-server\">"
    222              "<x xmlns=\"http://jabber.org/protocol/muc#user\">"
    223               "<item affiliation=\"owner\" role=\"participant\"/>"
    224              "</x>"
    225             "</presence>";
    226     TEST_OK(engine->HandleInput(input.c_str(), input.length()));
    227     TEST_EQ(chatroom_handler.StrClear(), "");
    228     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_REQUESTED_ENTER);
    229 
    230     input = "<presence from=\"darkcave@my-server/secondwitch\" to=\"david@my-server\">"
    231              "<x xmlns=\"http://jabber.org/protocol/muc#user\">"
    232               "<item affiliation=\"member\" role=\"participant\"/>"
    233              "</x>"
    234             "</presence>";
    235     TEST_OK(engine->HandleInput(input.c_str(), input.length()));
    236     TEST_EQ(chatroom_handler.StrClear(), "");
    237     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_REQUESTED_ENTER);
    238 
    239     input = "<presence from=\"darkcave@my-server/thirdwitch\" to=\"david@my-server\">"
    240              "<x xmlns=\"http://jabber.org/protocol/muc#user\">"
    241               "<item affiliation=\"member\" role=\"participant\"/>"
    242              "</x>"
    243             "</presence>";
    244     TEST_OK(engine->HandleInput(input.c_str(), input.length()));
    245     TEST_EQ(chatroom_handler.StrClear(),
    246       "[ChatroomEnteredStatus status: success]");
    247     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_IN_ROOM);
    248 
    249     // simulate somebody else entering the room after we entered
    250     input = "<presence from=\"darkcave@my-server/fourthwitch\" to=\"david@my-server\">"
    251              "<x xmlns=\"http://jabber.org/protocol/muc#user\">"
    252               "<item affiliation=\"member\" role=\"participant\"/>"
    253              "</x>"
    254             "</presence>";
    255     TEST_OK(engine->HandleInput(input.c_str(), input.length()));
    256     TEST_EQ(chatroom_handler.StrClear(), "[MemberEntered darkcave@my-server/fourthwitch]");
    257     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_IN_ROOM);
    258 
    259     // simulate somebody else leaving the room after we entered
    260     input = "<presence from=\"darkcave@my-server/secondwitch\" 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(), "[MemberExited darkcave@my-server/secondwitch]");
    267     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_IN_ROOM);
    268 
    269     // try to leave the room
    270     chatroom->RequestExitChatroom();
    271     TEST_EQ(chatroom_handler.StrClear(), "");
    272     TEST_EQ(handler.OutputActivity(),
    273       "<presence to=\"darkcave@my-server/thirdwitch\" type=\"unavailable\"/>");
    274     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_REQUESTED_EXIT);
    275 
    276     // simulate the server and test the client
    277     input = "<presence from=\"darkcave@my-server/thirdwitch\" to=\"david@my-server\" type=\"unavailable\">"
    278              "<x xmlns=\"http://jabber.org/protocol/muc#user\">"
    279               "<item affiliation=\"member\" role=\"participant\"/>"
    280              "</x>"
    281             "</presence>";
    282     TEST_OK(engine->HandleInput(input.c_str(), input.length()));
    283     TEST_EQ(chatroom_handler.StrClear(),
    284       "[ChatroomExitedStatus status: requested]");
    285     TEST_EQ(chatroom->state(), XMPP_CHATROOM_STATE_NOT_IN_ROOM);
    286   }
    287 
    288 };
    289 
    290 // A global function that creates the test suite for this set of tests.
    291 TestBase* ChatroomModuleTest_Create() {
    292   TestSuite* suite = new TestSuite("ChatroomModuleTest");
    293   ADD_TEST(suite, XmppChatroomModuleTest, TestEnterExitChatroom);
    294   return suite;
    295 }
    296 
    297 }
    298