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
WriteEnteredStatus(std::ostream & os,XmppChatroomEnteredStatus status)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
WriteExitedStatus(std::ostream & os,XmppChatroomExitedStatus status)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:
XmppTestChatroomHandler()97 XmppTestChatroomHandler() {}
~XmppTestChatroomHandler()98 virtual ~XmppTestChatroomHandler() {}
99
ChatroomEnteredStatus(XmppChatroomModule * room,XmppChatroomEnteredStatus status)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
ChatroomExitedStatus(XmppChatroomModule * room,XmppChatroomExitedStatus status)109 void ChatroomExitedStatus(XmppChatroomModule* room,
110 XmppChatroomExitedStatus status) {
111 RTC_UNUSED(room);
112 ss_ <<"[ChatroomExitedStatus status: ";
113 WriteExitedStatus(ss_, status);
114 ss_ <<"]";
115 }
116
MemberEntered(XmppChatroomModule * room,const XmppChatroomMember * entered_member)117 void MemberEntered(XmppChatroomModule* room,
118 const XmppChatroomMember* entered_member) {
119 RTC_UNUSED(room);
120 ss_ << "[MemberEntered " << entered_member->member_jid().Str() << "]";
121 }
122
MemberExited(XmppChatroomModule * room,const XmppChatroomMember * exited_member)123 void MemberExited(XmppChatroomModule* room,
124 const XmppChatroomMember* exited_member) {
125 RTC_UNUSED(room);
126 ss_ << "[MemberExited " << exited_member->member_jid().Str() << "]";
127 }
128
MemberChanged(XmppChatroomModule * room,const XmppChatroomMember * changed_member)129 void MemberChanged(XmppChatroomModule* room,
130 const XmppChatroomMember* changed_member) {
131 RTC_UNUSED(room);
132 ss_ << "[MemberChanged " << changed_member->member_jid().Str() << "]";
133 }
134
MessageReceived(XmppChatroomModule * room,const XmlElement & message)135 virtual void MessageReceived(XmppChatroomModule* room, const XmlElement& message) {
136 RTC_UNUSED2(room, message);
137 }
138
139
Str()140 std::string Str() {
141 return ss_.str();
142 }
143
StrClear()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:
XmppChatroomModuleTest()158 XmppChatroomModuleTest() {}
159
TestEnterExitChatroom()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.
ChatroomModuleTest_Create()274 TestBase* ChatroomModuleTest_Create() {
275 TestSuite* suite = new TestSuite("ChatroomModuleTest");
276 ADD_TEST(suite, XmppChatroomModuleTest, TestEnterExitChatroom);
277 return suite;
278 }
279
280 }
281