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