1 /*
2 * Copyright (C) 2004-2020 ZNC, see the NOTICE file for details.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gtest/gtest.h>
18 #include <gmock/gmock.h>
19 #include "IRCTest.h"
20
21 using ::testing::IsEmpty;
22 using ::testing::ElementsAre;
23
24 class ClientTest : public IRCTest {
25 protected:
testPass(const CString & sInput,const CString & sUser,const CString & sIdentifier,const CString & sNetwork,const CString & sPass) const26 void testPass(const CString& sInput, const CString& sUser,
27 const CString& sIdentifier, const CString& sNetwork,
28 const CString& sPass) const {
29 CClient client;
30 client.ParsePass(sInput);
31 EXPECT_EQ(client.m_sUser, sUser);
32 EXPECT_EQ(client.m_sIdentifier, sIdentifier);
33 EXPECT_EQ(client.m_sNetwork, sNetwork);
34 EXPECT_EQ(client.m_sPass, sPass);
35 }
36
testUser(const CString & sInput,const CString & sUser,const CString & sIdentifier,const CString & sNetwork) const37 void testUser(const CString& sInput, const CString& sUser,
38 const CString& sIdentifier, const CString& sNetwork) const {
39 CClient client;
40 client.ParseUser(sInput);
41 EXPECT_EQ(client.m_sUser, sUser);
42 EXPECT_EQ(client.m_sIdentifier, sIdentifier);
43 EXPECT_EQ(client.m_sNetwork, sNetwork);
44 }
45 };
46
TEST_F(ClientTest,Pass)47 TEST_F(ClientTest, Pass) {
48 // clang-format off
49 testPass("p@ss#w0rd", "", "", "", "p@ss#w0rd");
50 testPass("user:p@ss#w0rd", "user", "", "", "p@ss#w0rd");
51 testPass("user/net-work:p@ss#w0rd", "user", "", "net-work", "p@ss#w0rd");
52 testPass("user@identifier:p@ss#w0rd", "user", "identifier", "", "p@ss#w0rd");
53 testPass("user@identifier/net-work:p@ss#w0rd", "user", "identifier", "net-work", "p@ss#w0rd");
54
55 testPass("user@znc.in:p@ss#w0rd", "user@znc.in", "", "", "p@ss#w0rd");
56 testPass("user@znc.in/net-work:p@ss#w0rd", "user@znc.in", "", "net-work", "p@ss#w0rd");
57 testPass("user@znc.in@identifier:p@ss#w0rd", "user@znc.in", "identifier", "", "p@ss#w0rd");
58 testPass("user@znc.in@identifier/net-work:p@ss#w0rd", "user@znc.in", "identifier", "net-work", "p@ss#w0rd");
59 // clang-format on
60 }
61
TEST_F(ClientTest,User)62 TEST_F(ClientTest, User) {
63 // clang-format off
64 testUser("user/net-work", "user", "", "net-work");
65 testUser("user@identifier", "user", "identifier", "");
66 testUser("user@identifier/net-work", "user", "identifier", "net-work");
67
68 testUser("user@znc.in/net-work", "user@znc.in", "", "net-work");
69 testUser("user@znc.in@identifier", "user@znc.in", "identifier", "");
70 testUser("user@znc.in@identifier/net-work", "user@znc.in", "identifier", "net-work");
71 // clang-format on
72 }
73
TEST_F(ClientTest,AccountNotify)74 TEST_F(ClientTest, AccountNotify) {
75 CMessage msg(":nick!user@host ACCOUNT accountname");
76 EXPECT_FALSE(m_pTestClient->HasAccountNotify());
77 m_pTestClient->PutClient(msg);
78 EXPECT_THAT(m_pTestClient->vsLines, IsEmpty());
79 m_pTestClient->SetAccountNotify(true);
80 EXPECT_TRUE(m_pTestClient->HasAccountNotify());
81 m_pTestClient->PutClient(msg);
82 EXPECT_THAT(m_pTestClient->vsLines, ElementsAre(msg.ToString()));
83 }
84
TEST_F(ClientTest,AwayNotify)85 TEST_F(ClientTest, AwayNotify) {
86 CMessage msg(":nick!user@host AWAY :message");
87 EXPECT_FALSE(m_pTestClient->HasAwayNotify());
88 m_pTestClient->PutClient(msg);
89 EXPECT_THAT(m_pTestClient->vsLines, IsEmpty());
90 m_pTestClient->SetAwayNotify(true);
91 EXPECT_TRUE(m_pTestClient->HasAwayNotify());
92 m_pTestClient->PutClient(msg);
93 EXPECT_THAT(m_pTestClient->vsLines, ElementsAre(msg.ToString()));
94 }
95
TEST_F(ClientTest,MultiPrefixWho)96 TEST_F(ClientTest, MultiPrefixWho) { // aka NAMESX
97 m_pTestSock->ReadLine(
98 ":server 005 guest PREFIX=(qaohv)~&@%+ NAMESX :are supported by this "
99 "server");
100 m_pTestClient->Reset();
101
102 CMessage msg(
103 ":kenny.chatspike.net 352 guest #test grawity broken.symlink "
104 "*.chatspike.net grawity H@%+ :0 Mantas M.");
105 CMessage extmsg(
106 ":kenny.chatspike.net 352 guest #test grawity broken.symlink "
107 "*.chatspike.net grawity H@%+ :0 Mantas M.");
108 EXPECT_FALSE(m_pTestClient->HasNamesx());
109 m_pTestClient->PutClient(extmsg);
110 EXPECT_THAT(m_pTestClient->vsLines, ElementsAre(msg.ToString()));
111 m_pTestClient->SetNamesx(true);
112 EXPECT_TRUE(m_pTestClient->HasNamesx());
113 m_pTestClient->PutClient(extmsg);
114 EXPECT_THAT(m_pTestClient->vsLines,
115 ElementsAre(msg.ToString(), extmsg.ToString()));
116 }
117
TEST_F(ClientTest,MultiPrefixNames)118 TEST_F(ClientTest, MultiPrefixNames) { // aka NAMESX
119 m_pTestSock->ReadLine(
120 ":server 005 guest PREFIX=(qaohv)~&@%+ NAMESX :are supported by this "
121 "server");
122 m_pTestClient->Reset();
123
124 CMessage msg(
125 ":hades.arpa 353 guest = #tethys :~aji &Attila @alyx +KindOne Argure");
126 CMessage extmsg(
127 ":hades.arpa 353 guest = #tethys :~&@%+aji &@Attila @+alyx +KindOne "
128 "Argure");
129 EXPECT_FALSE(m_pTestClient->HasNamesx());
130 m_pTestClient->PutClient(extmsg);
131 EXPECT_THAT(m_pTestClient->vsLines, ElementsAre(msg.ToString()));
132 m_pTestClient->SetNamesx(true);
133 EXPECT_TRUE(m_pTestClient->HasNamesx());
134 m_pTestClient->PutClient(extmsg);
135 EXPECT_THAT(m_pTestClient->vsLines,
136 ElementsAre(msg.ToString(), extmsg.ToString()));
137 }
138
TEST_F(ClientTest,UserhostInNames)139 TEST_F(ClientTest, UserhostInNames) { // aka UHNAMES
140 m_pTestSock->ReadLine(
141 ":server 005 guest UHNAMES :are supported by this server");
142 m_pTestClient->Reset();
143
144 CMessage msg(":irc.bnc.im 353 guest = #atheme :Rylee somasonic");
145 CMessage extmsg(
146 ":irc.bnc.im 353 guest = #atheme :Rylee!rylai@localhost "
147 "somasonic!andrew@somasonic.org");
148 EXPECT_FALSE(m_pTestClient->HasUHNames());
149 m_pTestClient->PutClient(extmsg);
150 EXPECT_THAT(m_pTestClient->vsLines, ElementsAre(msg.ToString()));
151 m_pTestClient->SetUHNames(true);
152 EXPECT_TRUE(m_pTestClient->HasUHNames());
153 m_pTestClient->PutClient(extmsg);
154 EXPECT_THAT(m_pTestClient->vsLines,
155 ElementsAre(msg.ToString(), extmsg.ToString()));
156 }
157
TEST_F(ClientTest,ExtendedJoin)158 TEST_F(ClientTest, ExtendedJoin) {
159 m_pTestSock->ReadLine(":server CAP * ACK :extended-join");
160 m_pTestClient->Reset();
161
162 CMessage msg(":nick!user@host JOIN #channel");
163 CMessage extmsg(":nick!user@host JOIN #channel account :Real Name");
164 EXPECT_FALSE(m_pTestClient->HasExtendedJoin());
165 m_pTestClient->PutClient(extmsg);
166 EXPECT_THAT(m_pTestClient->vsLines, ElementsAre(msg.ToString()));
167 m_pTestClient->SetExtendedJoin(true);
168 EXPECT_TRUE(m_pTestClient->HasExtendedJoin());
169 m_pTestClient->PutClient(extmsg);
170 EXPECT_THAT(m_pTestClient->vsLines,
171 ElementsAre(msg.ToString(), extmsg.ToString()));
172 }
173
TEST_F(ClientTest,StatusMsg)174 TEST_F(ClientTest, StatusMsg) {
175 m_pTestSock->ReadLine(
176 ":irc.znc.in 001 me :Welcome to the Internet Relay Network me");
177 m_pTestSock->ReadLine(
178 ":irc.znc.in 005 me CHANTYPES=# PREFIX=(ov)@+ STATUSMSG=@+ :are "
179 "supported by this server");
180
181 m_pTestUser->SetAutoClearChanBuffer(false);
182 m_pTestClient->ReadLine("PRIVMSG @#chan :hello ops");
183
184 EXPECT_EQ(m_pTestChan->GetBuffer().Size(), 1u);
185
186 m_pTestUser->SetTimestampPrepend(false);
187 EXPECT_EQ(m_pTestChan->GetBuffer().GetLine(0, *m_pTestClient),
188 ":me PRIVMSG @#chan :hello ops");
189 }
190
TEST_F(ClientTest,TagSupport)191 TEST_F(ClientTest, TagSupport) {
192 m_pTestClient->SetTagSupport("test-tag", true);
193 CMessage tagmsg("@test-tag=yes;invalid-tag=no :nick!user@host PRIVMSG #chan :text");
194 m_pTestClient->PutClient(tagmsg);
195
196 EXPECT_THAT(m_pTestClient->vsLines,
197 ElementsAre("@test-tag=yes :nick!user@host PRIVMSG #chan :text"));
198
199 m_pTestClient->Reset();
200 m_pTestClient->SetTagSupport("test-tag", false);
201 m_pTestClient->PutClient(tagmsg);
202
203 EXPECT_THAT(m_pTestClient->vsLines,
204 ElementsAre(":nick!user@host PRIVMSG #chan :text"));
205 }
206
TEST_F(ClientTest,OnUserCTCPReplyMessage)207 TEST_F(ClientTest, OnUserCTCPReplyMessage) {
208 CMessage msg("NOTICE someone :\001VERSION 123\001");
209 m_pTestModule->eAction = CModule::HALT;
210 m_pTestClient->ReadLine(msg.ToString());
211
212 CString sReply =
213 "NOTICE someone :\x01VERSION 123 via " + CZNC::GetTag(false) + "\x01";
214
215 EXPECT_THAT(m_pTestModule->vsHooks, ElementsAre("OnUserCTCPReplyMessage"));
216 EXPECT_THAT(m_pTestModule->vsMessages, ElementsAre(sReply));
217 EXPECT_THAT(m_pTestModule->vNetworks, ElementsAre(nullptr));
218 EXPECT_THAT(m_pTestModule->vClients, ElementsAre(m_pTestClient));
219 EXPECT_THAT(m_pTestModule->vChannels, ElementsAre(nullptr));
220 EXPECT_THAT(m_pTestSock->vsLines, IsEmpty()); // halt
221
222 m_pTestModule->eAction = CModule::CONTINUE;
223 m_pTestClient->ReadLine(msg.ToString());
224 EXPECT_THAT(m_pTestSock->vsLines, ElementsAre(sReply));
225 }
226
TEST_F(ClientTest,OnUserCTCPMessage)227 TEST_F(ClientTest, OnUserCTCPMessage) {
228 CMessage msg("PRIVMSG someone :\001VERSION\001");
229 m_pTestModule->eAction = CModule::HALT;
230 m_pTestClient->ReadLine(msg.ToString());
231
232 EXPECT_THAT(m_pTestModule->vsHooks, ElementsAre("OnUserCTCPMessage"));
233 EXPECT_THAT(m_pTestModule->vsMessages, ElementsAre(msg.ToString()));
234 EXPECT_THAT(m_pTestModule->vNetworks, ElementsAre(nullptr));
235 EXPECT_THAT(m_pTestModule->vClients, ElementsAre(m_pTestClient));
236 EXPECT_THAT(m_pTestModule->vChannels, ElementsAre(nullptr));
237 EXPECT_THAT(m_pTestSock->vsLines, IsEmpty()); // halt
238
239 m_pTestModule->eAction = CModule::CONTINUE;
240 m_pTestClient->ReadLine(msg.ToString());
241 EXPECT_THAT(m_pTestSock->vsLines, ElementsAre(msg.ToString()));
242 }
243
TEST_F(ClientTest,OnUserActionMessage)244 TEST_F(ClientTest, OnUserActionMessage) {
245 CMessage msg("PRIVMSG #chan :\001ACTION acts\001");
246 m_pTestModule->eAction = CModule::HALT;
247 m_pTestClient->ReadLine(msg.ToString());
248
249 EXPECT_THAT(m_pTestModule->vsHooks, ElementsAre("OnUserActionMessage"));
250 EXPECT_THAT(m_pTestModule->vsMessages, ElementsAre(msg.ToString()));
251 EXPECT_THAT(m_pTestModule->vNetworks, ElementsAre(nullptr));
252 EXPECT_THAT(m_pTestModule->vClients, ElementsAre(m_pTestClient));
253 EXPECT_THAT(m_pTestModule->vChannels, ElementsAre(m_pTestChan));
254 EXPECT_THAT(m_pTestSock->vsLines, IsEmpty()); // halt
255
256 m_pTestModule->eAction = CModule::CONTINUE;
257 m_pTestClient->ReadLine(msg.ToString());
258 EXPECT_THAT(m_pTestSock->vsLines, ElementsAre(msg.ToString()));
259 }
260
TEST_F(ClientTest,OnUserTextMessage)261 TEST_F(ClientTest, OnUserTextMessage) {
262 CMessage msg("PRIVMSG #chan :text");
263 m_pTestModule->eAction = CModule::HALT;
264 m_pTestClient->ReadLine(msg.ToString());
265
266 EXPECT_THAT(m_pTestModule->vsHooks, ElementsAre("OnUserTextMessage"));
267 EXPECT_THAT(m_pTestModule->vsMessages, ElementsAre(msg.ToString()));
268 EXPECT_THAT(m_pTestModule->vNetworks, ElementsAre(nullptr));
269 EXPECT_THAT(m_pTestModule->vClients, ElementsAre(m_pTestClient));
270 EXPECT_THAT(m_pTestModule->vChannels, ElementsAre(m_pTestChan));
271 EXPECT_THAT(m_pTestSock->vsLines, IsEmpty()); // halt
272
273 m_pTestModule->eAction = CModule::CONTINUE;
274 m_pTestClient->ReadLine(msg.ToString());
275 EXPECT_THAT(m_pTestSock->vsLines, ElementsAre(msg.ToString()));
276 }
277
TEST_F(ClientTest,OnUserNoticeMessage)278 TEST_F(ClientTest, OnUserNoticeMessage) {
279 CMessage msg("NOTICE #chan :text");
280 m_pTestModule->eAction = CModule::HALT;
281 m_pTestClient->ReadLine(msg.ToString());
282
283 EXPECT_THAT(m_pTestModule->vsHooks, ElementsAre("OnUserNoticeMessage"));
284 EXPECT_THAT(m_pTestModule->vsMessages, ElementsAre(msg.ToString()));
285 EXPECT_THAT(m_pTestModule->vNetworks, ElementsAre(nullptr));
286 EXPECT_THAT(m_pTestModule->vClients, ElementsAre(m_pTestClient));
287 EXPECT_THAT(m_pTestModule->vChannels, ElementsAre(m_pTestChan));
288 EXPECT_THAT(m_pTestSock->vsLines, IsEmpty()); // halt
289
290 m_pTestModule->eAction = CModule::CONTINUE;
291 m_pTestClient->ReadLine(msg.ToString());
292 EXPECT_THAT(m_pTestSock->vsLines, ElementsAre(msg.ToString()));
293 }
294
TEST_F(ClientTest,OnUserJoinMessage)295 TEST_F(ClientTest, OnUserJoinMessage) {
296 CMessage msg("JOIN #chan key");
297 m_pTestModule->eAction = CModule::HALT;
298 m_pTestClient->ReadLine(msg.ToString());
299
300 EXPECT_THAT(m_pTestModule->vsHooks, ElementsAre("OnUserJoinMessage"));
301 EXPECT_THAT(m_pTestModule->vsMessages, ElementsAre(msg.ToString()));
302 EXPECT_THAT(m_pTestModule->vNetworks, ElementsAre(nullptr));
303 EXPECT_THAT(m_pTestModule->vClients, ElementsAre(m_pTestClient));
304 EXPECT_THAT(m_pTestModule->vChannels, ElementsAre(m_pTestChan));
305 EXPECT_THAT(m_pTestSock->vsLines, IsEmpty()); // halt
306
307 m_pTestModule->eAction = CModule::CONTINUE;
308 m_pTestClient->ReadLine(msg.ToString());
309 EXPECT_THAT(m_pTestSock->vsLines, ElementsAre(msg.ToString()));
310 }
311
TEST_F(ClientTest,OnUserPartMessage)312 TEST_F(ClientTest, OnUserPartMessage) {
313 m_pTestChan->SetIsOn(true);
314 CMessage msg("PART #chan");
315 m_pTestModule->eAction = CModule::HALT;
316 m_pTestClient->ReadLine(msg.ToString());
317
318 EXPECT_THAT(m_pTestModule->vsHooks, ElementsAre("OnUserPartMessage"));
319 EXPECT_THAT(m_pTestModule->vsMessages, ElementsAre(msg.ToString()));
320 EXPECT_THAT(m_pTestModule->vNetworks, ElementsAre(nullptr));
321 EXPECT_THAT(m_pTestModule->vClients, ElementsAre(m_pTestClient));
322 EXPECT_THAT(m_pTestModule->vChannels, ElementsAre(m_pTestChan));
323 EXPECT_THAT(m_pTestSock->vsLines, IsEmpty()); // halt
324
325 m_pTestModule->eAction = CModule::CONTINUE;
326 m_pTestClient->ReadLine(msg.ToString());
327 EXPECT_THAT(m_pTestSock->vsLines, ElementsAre(msg.ToString()));
328 }
329
TEST_F(ClientTest,OnUserTopicMessage)330 TEST_F(ClientTest, OnUserTopicMessage) {
331 CMessage msg("TOPIC #chan :topic");
332 m_pTestModule->eAction = CModule::HALT;
333 m_pTestClient->ReadLine(msg.ToString());
334
335 EXPECT_THAT(m_pTestModule->vsHooks, ElementsAre("OnUserTopicMessage"));
336 EXPECT_THAT(m_pTestModule->vsMessages, ElementsAre(msg.ToString()));
337 EXPECT_THAT(m_pTestModule->vNetworks, ElementsAre(nullptr));
338 EXPECT_THAT(m_pTestModule->vClients, ElementsAre(m_pTestClient));
339 EXPECT_THAT(m_pTestModule->vChannels, ElementsAre(m_pTestChan));
340 EXPECT_THAT(m_pTestSock->vsLines, IsEmpty()); // halt
341
342 m_pTestModule->eAction = CModule::CONTINUE;
343 m_pTestClient->ReadLine(msg.ToString());
344 EXPECT_THAT(m_pTestSock->vsLines, ElementsAre(msg.ToString()));
345 }
346
TEST_F(ClientTest,OnUserQuitMessage)347 TEST_F(ClientTest, OnUserQuitMessage) {
348 CMessage msg("QUIT :reason");
349 m_pTestModule->eAction = CModule::HALT;
350 m_pTestClient->ReadLine(msg.ToString());
351
352 EXPECT_THAT(m_pTestModule->vsHooks, ElementsAre("OnUserQuitMessage"));
353 EXPECT_THAT(m_pTestModule->vsMessages, ElementsAre(msg.ToString()));
354 EXPECT_THAT(m_pTestModule->vNetworks, ElementsAre(nullptr));
355 EXPECT_THAT(m_pTestModule->vClients, ElementsAre(m_pTestClient));
356 EXPECT_THAT(m_pTestModule->vChannels, ElementsAre(nullptr));
357 EXPECT_THAT(m_pTestSock->vsLines, IsEmpty()); // halt
358
359 m_pTestModule->eAction = CModule::CONTINUE;
360 m_pTestClient->ReadLine(msg.ToString());
361 EXPECT_THAT(m_pTestSock->vsLines, IsEmpty()); // quit is never forwarded
362 }
363
TEST_F(ClientTest,OnSendToClientMessage)364 TEST_F(ClientTest, OnSendToClientMessage) {
365 CMessage msg("PRIVMSG #chan :text");
366 m_pTestModule->eAction = CModule::HALT;
367 m_pTestModule->bSendHooks = true;
368 m_pTestClient->PutClient(msg.ToString());
369
370 EXPECT_THAT(m_pTestModule->vsHooks, ElementsAre("OnSendToClientMessage"));
371 EXPECT_THAT(m_pTestModule->vsMessages, ElementsAre(msg.ToString()));
372 EXPECT_THAT(m_pTestModule->vNetworks, ElementsAre(m_pTestClient->GetNetwork()));
373 EXPECT_THAT(m_pTestModule->vClients, ElementsAre(m_pTestClient));
374 EXPECT_THAT(m_pTestModule->vChannels, ElementsAre(nullptr));
375 EXPECT_THAT(m_pTestSock->vsLines, IsEmpty()); // halt
376
377 m_pTestModule->eAction = CModule::CONTINUE;
378 m_pTestClient->ReadLine(msg.ToString());
379
380 EXPECT_THAT(m_pTestSock->vsLines, ElementsAre(msg.ToString()));
381 m_pTestModule->bSendHooks = false;
382 }
383