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