]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/testsuite.cpp
Merge pull request #984 from Renegade334/modules-exempt-uline
[user/henk/code/inspircd.git] / src / testsuite.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2009 Robin Burchell <robin+git@viroteck.net>
5  *   Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
6  *   Copyright (C) 2008 Dennis Friis <peavey@inspircd.org>
7  *
8  * This file is part of InspIRCd.  InspIRCd is free software: you can
9  * redistribute it and/or modify it under the terms of the GNU General Public
10  * License as published by the Free Software Foundation, version 2.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21
22 #ifdef INSPIRCD_ENABLE_TESTSUITE
23
24 #include "inspircd.h"
25 #include "testsuite.h"
26 #include <iostream>
27
28 class TestSuiteThread : public Thread
29 {
30  public:
31         TestSuiteThread() : Thread()
32         {
33         }
34
35         virtual ~TestSuiteThread()
36         {
37         }
38
39         virtual void Run()
40         {
41                 while (GetExitFlag() == false)
42                 {
43                         std::cout << "Test suite thread run...\n";
44                         sleep(5);
45                 }
46         }
47 };
48
49 TestSuite::TestSuite()
50 {
51         std::cout << "\n\n*** STARTING TESTSUITE ***\n";
52
53         std::string modname;
54         char choice;
55
56         while (1)
57         {
58                 std::cout << "(1) Call all module OnRunTestSuite() methods\n";
59                 std::cout << "(2) Load a module\n";
60                 std::cout << "(3) Unload a module\n";
61                 std::cout << "(4) Threading tests\n";
62                 std::cout << "(5) Wildcard and CIDR tests\n";
63                 std::cout << "(6) Comma sepstream tests\n";
64                 std::cout << "(7) Space sepstream tests\n";
65                 std::cout << "(8) UID generation tests\n";
66
67                 std::cout << std::endl << "(X) Exit test suite\n";
68
69                 std::cout << "\nChoices (Enter one or more options as a list then press enter, e.g. 15X): ";
70                 std::cin >> choice;
71
72                 if (!choice)
73                         continue;
74
75                 switch (choice)
76                 {
77                         case '1':
78                         {
79                                 const ModuleManager::ModuleMap& mods = ServerInstance->Modules->GetModules();
80                                 for (ModuleManager::ModuleMap::const_iterator i = mods.begin(); i != mods.end(); ++i)
81                                         i->second->OnRunTestSuite();
82                                 break;
83                         }
84                         case '2':
85                                 std::cout << "Enter module filename to load: ";
86                                 std::cin >> modname;
87                                 std::cout << (ServerInstance->Modules->Load(modname.c_str()) ? "\nSUCCESS!\n" : "\nFAILURE\n");
88                                 break;
89                         case '3':
90                                 std::cout << "Enter module filename to unload: ";
91                                 std::cin >> modname;
92                                 {
93                                         Module* m = ServerInstance->Modules->Find(modname);
94                                         std::cout << (ServerInstance->Modules->Unload(m) ? "\nSUCCESS!\n" : "\nFAILURE\n");
95                                         ServerInstance->AtomicActions.Run();
96                                 }
97                                 break;
98                         case '4':
99                                 std::cout << (DoThreadTests() ? "\nSUCCESS!\n" : "\nFAILURE\n");
100                                 break;
101                         case '5':
102                                 std::cout << (DoWildTests() ? "\nSUCCESS!\n" : "\nFAILURE\n");
103                                 break;
104                         case '6':
105                                 std::cout << (DoCommaSepStreamTests() ? "\nSUCCESS!\n" : "\nFAILURE\n");
106                                 break;
107                         case '7':
108                                 std::cout << (DoSpaceSepStreamTests() ? "\nSUCCESS!\n" : "\nFAILURE\n");
109                                 break;
110                         case '8':
111                                 std::cout << (DoGenerateUIDTests() ? "\nSUCCESS!\n" : "\nFAILURE\n");
112                                 break;
113                         case 'X':
114                                 return;
115                                 break;
116                         default:
117                                 std::cout << "Invalid option\n";
118                                 break;
119                 }
120                 std::cout << std::endl;
121         }
122 }
123
124 /* Test that x matches y with match() */
125 #define WCTEST(x, y) std::cout << "match(\"" << x << "\",\"" << y "\") " << ((passed = (InspIRCd::Match(x, y, NULL))) ? " SUCCESS!\n" : " FAILURE\n")
126 /* Test that x does not match y with match() */
127 #define WCTESTNOT(x, y) std::cout << "!match(\"" << x << "\",\"" << y "\") " << ((passed = ((!InspIRCd::Match(x, y, NULL)))) ? " SUCCESS!\n" : " FAILURE\n")
128
129 /* Test that x matches y with match() and cidr enabled */
130 #define CIDRTEST(x, y) std::cout << "match(\"" << x << "\",\"" << y "\", true) " << ((passed = (InspIRCd::MatchCIDR(x, y, NULL))) ? " SUCCESS!\n" : " FAILURE\n")
131 /* Test that x does not match y with match() and cidr enabled */
132 #define CIDRTESTNOT(x, y) std::cout << "!match(\"" << x << "\",\"" << y "\", true) " << ((passed = ((!InspIRCd::MatchCIDR(x, y, NULL)))) ? " SUCCESS!\n" : " FAILURE\n")
133
134 bool TestSuite::DoWildTests()
135 {
136         std::cout << "\n\nWildcard and CIDR tests\n\n";
137         bool passed = false;
138
139         WCTEST("foobar", "*");
140         WCTEST("foobar", "foo*");
141         WCTEST("foobar", "*bar");
142         WCTEST("foobar", "foo??r");
143         WCTEST("foobar.test", "fo?bar.*t");
144         WCTEST("foobar.test", "fo?bar.t*t");
145         WCTEST("foobar.tttt", "fo?bar.**t");
146         WCTEST("foobar", "foobar");
147         WCTEST("foobar", "foo***bar");
148         WCTEST("foobar", "*foo***bar");
149         WCTEST("foobar", "**foo***bar");
150         WCTEST("foobar", "**foobar*");
151         WCTEST("foobar", "**foobar**");
152         WCTEST("foobar", "**foobar");
153         WCTEST("foobar", "**f?*?ar");
154         WCTEST("foobar", "**f?*b?r");
155         WCTEST("foofar", "**f?*f*r");
156         WCTEST("foofar", "**f?*f*?");
157         WCTEST("r", "*");
158         WCTEST("", "");
159         WCTEST("test@foo.bar.test", "*@*.bar.test");
160         WCTEST("test@foo.bar.test", "*test*@*.bar.test");
161         WCTEST("test@foo.bar.test", "*@*test");
162
163         WCTEST("a", "*a");
164         WCTEST("aa", "*a");
165         WCTEST("aaa", "*a");
166         WCTEST("aaaa", "*a");
167         WCTEST("aaaaa", "*a");
168         WCTEST("aaaaaa", "*a");
169         WCTEST("aaaaaaa", "*a");
170         WCTEST("aaaaaaaa", "*a");
171         WCTEST("aaaaaaaaa", "*a");
172         WCTEST("aaaaaaaaaa", "*a");
173         WCTEST("aaaaaaaaaaa", "*a");
174
175         WCTESTNOT("foobar", "bazqux");
176         WCTESTNOT("foobar", "*qux");
177         WCTESTNOT("foobar", "foo*x");
178         WCTESTNOT("foobar", "baz*");
179         WCTESTNOT("foobar", "foo???r");
180         WCTESTNOT("foobar", "foobars");
181         WCTESTNOT("foobar", "**foobar**h");
182         WCTESTNOT("foobar", "**foobar**h*");
183         WCTESTNOT("foobar", "**f??*bar?");
184         WCTESTNOT("foobar", "");
185         WCTESTNOT("", "foobar");
186         WCTESTNOT("OperServ", "O");
187         WCTESTNOT("O", "OperServ");
188         WCTESTNOT("foobar.tst", "fo?bar.*g");
189         WCTESTNOT("foobar.test", "fo?bar.*tt");
190
191         CIDRTEST("brain@1.2.3.4", "*@1.2.0.0/16");
192         CIDRTEST("brain@1.2.3.4", "*@1.2.3.0/24");
193         CIDRTEST("192.168.3.97", "192.168.3.0/24");
194
195         CIDRTESTNOT("brain@1.2.3.4", "x*@1.2.0.0/16");
196         CIDRTESTNOT("brain@1.2.3.4", "*@1.3.4.0/24");
197         CIDRTESTNOT("1.2.3.4", "1.2.4.0/24");
198         CIDRTESTNOT("brain@1.2.3.4", "*@/24");
199         CIDRTESTNOT("brain@1.2.3.4", "@1.2.3.4/9");
200         CIDRTESTNOT("brain@1.2.3.4", "@");
201         CIDRTESTNOT("brain@1.2.3.4", "");
202
203         return true;
204 }
205
206
207 #define STREQUALTEST(x, y) std::cout << "==(\"" << x << ",\"" << y "\") " << ((passed = (x == y)) ? "SUCCESS\n" : "FAILURE\n")
208
209 bool TestSuite::DoCommaSepStreamTests()
210 {
211         bool passed = false;
212         irc::commasepstream items("this,is,a,comma,stream");
213         std::string item;
214         int idx = 0;
215
216         while (items.GetToken(item))
217         {
218                 idx++;
219
220                 switch (idx)
221                 {
222                         case 1:
223                                 STREQUALTEST(item, "this");
224                                 break;
225                         case 2:
226                                 STREQUALTEST(item, "is");
227                                 break;
228                         case 3:
229                                 STREQUALTEST(item, "a");
230                                 break;
231                         case 4:
232                                 STREQUALTEST(item, "comma");
233                                 break;
234                         case 5:
235                                 STREQUALTEST(item, "stream");
236                                 break;
237                         default:
238                                 std::cout << "COMMASEPSTREAM: FAILURE: Got an index too many! " << idx << " items\n";
239                                 break;
240                 }
241         }
242
243         return true;
244 }
245
246 bool TestSuite::DoSpaceSepStreamTests()
247 {
248         bool passed = false;
249
250         irc::spacesepstream list("this is a space stream");
251         std::string item;
252         int idx = 0;
253
254         while (list.GetToken(item))
255         {
256                 idx++;
257
258                 switch (idx)
259                 {
260                         case 1:
261                                 STREQUALTEST(item, "this");
262                                 break;
263                         case 2:
264                                 STREQUALTEST(item, "is");
265                                 break;
266                         case 3:
267                                 STREQUALTEST(item, "a");
268                                 break;
269                         case 4:
270                                 STREQUALTEST(item, "space");
271                                 break;
272                         case 5:
273                                 STREQUALTEST(item, "stream");
274                                 break;
275                         default:
276                                 std::cout << "SPACESEPSTREAM: FAILURE: Got an index too many! " << idx << " items\n";
277                                 break;
278                 }
279         }
280         return true;
281 }
282
283 bool TestSuite::DoThreadTests()
284 {
285         std::string anything;
286         ThreadEngine* te = NULL;
287
288         std::cout << "Creating new ThreadEngine class...\n";
289         try
290         {
291                 te = new ThreadEngine;
292         }
293         catch (...)
294         {
295                 std::cout << "Creation failed, test failure.\n";
296                 return false;
297         }
298         std::cout << "Creation success, type " << te->GetName() << "\n";
299
300         std::cout << "Allocate: new TestSuiteThread...\n";
301         TestSuiteThread* tst = new TestSuiteThread();
302
303         std::cout << "ThreadEngine::Create on TestSuiteThread...\n";
304         try
305         {
306                 try
307                 {
308                         te->Start(tst);
309                 }
310                 catch (CoreException &ce)
311                 {
312                         std::cout << "Failure: " << ce.GetReason() << std::endl;
313                 }
314         }
315         catch (...)
316         {
317                 std::cout << "Failure, unhandled exception\n";
318         }
319
320         std::cout << "Type any line and press enter to end test.\n";
321         std::cin >> anything;
322
323         /* Thread engine auto frees thread on delete */
324         std::cout << "Waiting for thread to exit... " << std::flush;
325         delete tst;
326         std::cout << "Done!\n";
327
328         std::cout << "Delete ThreadEngine... ";
329         delete te;
330         std::cout << "Done!\n";
331
332         return true;
333 }
334
335 bool TestSuite::DoGenerateUIDTests()
336 {
337         const unsigned int UUID_LENGTH = UIDGenerator::UUID_LENGTH;
338         UIDGenerator uidgen;
339         uidgen.init(ServerInstance->Config->GetSID());
340         std::string first_uid = uidgen.GetUID();
341
342         if (first_uid.length() != UUID_LENGTH)
343         {
344                 std::cout << "GENERATEUID: Generated UID is " << first_uid.length() << " characters long instead of " << UUID_LENGTH-1 << std::endl;
345                 return false;
346         }
347
348         if (uidgen.current_uid.c_str()[UUID_LENGTH] != '\0')
349         {
350                 std::cout << "GENERATEUID: The null terminator is missing from the end of current_uid" << std::endl;
351                 return false;
352         }
353
354         // The correct UID when generating one for the first time is ...AAAAAA
355         std::string correct_uid = ServerInstance->Config->sid + std::string(UUID_LENGTH - 3, 'A');
356         if (first_uid != correct_uid)
357         {
358                 std::cout << "GENERATEUID: Generated an invalid first UID: " << first_uid << " instead of " << correct_uid << std::endl;
359                 return false;
360         }
361
362         // Set current_uid to be ...Z99999
363         uidgen.current_uid[3] = 'Z';
364         for (unsigned int i = 4; i < UUID_LENGTH; i++)
365                 uidgen.current_uid[i] = '9';
366
367         // Store the UID we'll be incrementing so we can display what's wrong later if necessary
368         std::string before_increment(uidgen.current_uid);
369         std::string generated_uid = uidgen.GetUID();
370
371         // Correct UID after incrementing ...Z99999 is ...0AAAAA
372         correct_uid = ServerInstance->Config->sid + "0" + std::string(UUID_LENGTH - 4, 'A');
373
374         if (generated_uid != correct_uid)
375         {
376                 std::cout << "GENERATEUID: Generated an invalid UID after incrementing " << before_increment << ": " << generated_uid << " instead of " << correct_uid << std::endl;
377                 return false;
378         }
379
380         // Set current_uid to be ...999999 to see if it rolls over correctly
381         for (unsigned int i = 3; i < UUID_LENGTH; i++)
382                 uidgen.current_uid[i] = '9';
383
384         before_increment.assign(uidgen.current_uid);
385         generated_uid = uidgen.GetUID();
386
387         // Correct UID after rolling over is the first UID we've generated (...AAAAAA)
388         if (generated_uid != first_uid)
389         {
390                 std::cout << "GENERATEUID: Generated an invalid UID after incrementing " << before_increment << ": " << generated_uid << " instead of " << first_uid << std::endl;
391                 return false;
392         }
393
394         return true;
395 }
396
397 TestSuite::~TestSuite()
398 {
399         std::cout << "\n\n*** END OF TEST SUITE ***\n";
400 }
401
402 #endif