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