vfs: check userland buffers before reading them.
[haiku.git] / src / tests / kits / app / RegistrarThreadManagerTest.cpp
blob1a47175dd63544fbfd25b73ee2f4ee0f5946b784
1 #include "RegistrarThreadManagerTest.h"
3 #include <cppunit/Test.h>
4 #include <cppunit/TestCaller.h>
5 #include <cppunit/TestSuite.h>
6 #include <TestApp.h>
7 #include <TestUtils.h>
9 #ifndef TEST_R5
10 #include "RegistrarThread.h"
11 #include "RegistrarThreadManager.h"
12 #endif // !TEST_R5
14 #include <stdio.h>
16 // Suite
17 CppUnit::Test*
18 RegistrarThreadManagerTest::Suite() {
19 CppUnit::TestSuite *suite = new CppUnit::TestSuite();
20 typedef CppUnit::TestCaller<RegistrarThreadManagerTest> TC;
22 suite->addTest( new TC("RegistrarThreadManager::Shutdown Test",
23 &RegistrarThreadManagerTest::ShutdownTest) );
24 suite->addTest( new TC("RegistrarThreadManager::Thread Limit Test",
25 &RegistrarThreadManagerTest::ThreadLimitTest) );
28 return suite;
31 #ifndef TEST_R5
32 // Base test thread class
33 class TestThread : public RegistrarThread {
34 public:
35 TestThread(const char *name, int32 priority, BMessenger managerMessenger)
36 : RegistrarThread(name, priority, managerMessenger)
40 void DoSomethingUseless() {
41 fIntVal++;
42 snooze(1000);
45 private:
46 int64 fIntVal;
49 // Test thread that terminates quickly
50 class TerminatingThread : public TestThread {
51 public:
52 TerminatingThread(const char *name, int32 priority, BMessenger managerMessenger)
53 : TestThread(name, priority, managerMessenger)
57 protected:
58 virtual status_t ThreadFunction() {
59 DoSomethingUseless();
60 fIsFinished = true;
61 return B_OK;
65 // Test thread that never terminates, but pays attention
66 // to its fShouldExit member
67 class WellBehavedInfiniteThread : public TestThread {
68 public:
69 WellBehavedInfiniteThread(const char *name, int32 priority, BMessenger managerMessenger)
70 : TestThread(name, priority, managerMessenger)
74 protected:
75 virtual status_t ThreadFunction() {
76 while (true) {
77 DoSomethingUseless();
78 if (fShouldExit)
79 break;
81 fIsFinished = true;
82 return B_OK;
86 // Test thread that never terminates and completely ignores
87 // its fShouldExit member
88 class NaughtyInfiniteThread : public TestThread {
89 public:
90 NaughtyInfiniteThread(const char *name, int32 priority, BMessenger managerMessenger)
91 : TestThread(name, priority, managerMessenger)
95 protected:
96 virtual status_t ThreadFunction() {
97 while (true) {
98 DoSomethingUseless();
100 fIsFinished = true;
101 return B_OK;
104 #endif // !TEST_R5
107 // setUp
108 void
109 RegistrarThreadManagerTest::setUp()
111 BTestCase::setUp();
112 #ifndef TEST_R5
113 // Setup our application
114 fApplication = new BTestApp("application/x-vnd.obos.RegistrarThreadManagerTest");
115 if (fApplication->Init() != B_OK) {
116 fprintf(stderr, "Failed to initialize application (perhaps the obos registrar isn't running?).\n");
117 delete fApplication;
118 fApplication = NULL;
120 #endif // !TEST_R5
123 // tearDown
124 void
125 RegistrarThreadManagerTest::tearDown()
127 #ifndef TEST_R5
128 // Terminate the Application
129 if (fApplication) {
130 fApplication->Terminate();
131 delete fApplication;
132 fApplication = NULL;
134 #endif // !TEST_R5
135 BTestCase::tearDown();
138 void
139 RegistrarThreadManagerTest::ShutdownTest()
141 #ifdef TEST_R5
142 Outputf("(no tests performed for R5 version)\n");
143 #else
144 NextSubTest();
145 status_t err = B_OK;
146 NextSubTest();
147 RegistrarThreadManager manager;
148 NextSubTest();
149 CHK(fApplication && fApplication->InitCheck() == B_OK);
150 NextSubTest();
151 // fApplication->AddHandler(&manager);
152 NextSubTest();
153 BMessenger managerMessenger(NULL, fApplication, &err);
154 // TODO: Do something about this...
155 if (err != B_OK) {
156 fprintf(stderr, "Fails because we try to init an Haiku BMessenger with a "
157 "BLooper from R5's libbe (more precisely a BTestApp living in libcppunit, "
158 "which is only linked against R5's libbe).\n");
160 NextSubTest();
161 CHK(err == B_OK && managerMessenger.IsValid());
162 NextSubTest();
164 // Launch a bunch of threads
165 const uint termThreads = 2;
166 const uint niceThreads = 2;
167 const uint evilThreads = 2;
169 for (uint i = 0; i < termThreads; i++) {
170 NextSubTest();
171 char name[1024];
172 sprintf(name, "terminating #%d", i);
173 RegistrarThread *thread = new TerminatingThread(name, B_NORMAL_PRIORITY, managerMessenger);
174 CHK(thread != NULL);
175 CHK(thread->InitCheck() == B_OK);
176 CHK(manager.LaunchThread(thread) == B_OK);
179 for (uint i = 0; i < niceThreads; i++) {
180 NextSubTest();
181 char name[1024];
182 sprintf(name, "nice #%d", i);
183 RegistrarThread *thread = new WellBehavedInfiniteThread(name, B_NORMAL_PRIORITY, managerMessenger);
184 CHK(thread != NULL);
185 CHK(thread->InitCheck() == B_OK);
186 CHK(manager.LaunchThread(thread) == B_OK);
189 for (uint i = 0; i < evilThreads; i++) {
190 NextSubTest();
191 char name[1024];
192 sprintf(name, "evil #%d", i);
193 RegistrarThread *thread = new NaughtyInfiniteThread(name, B_NORMAL_PRIORITY, managerMessenger);
194 CHK(thread != NULL);
195 CHK(thread->InitCheck() == B_OK);
196 CHK(manager.LaunchThread(thread) == B_OK);
199 // Check the number of threads before doing a cleanup
200 NextSubTest(); // <= 13
201 CHK(manager.ThreadCount() == (termThreads + niceThreads + evilThreads));
203 // Do the cleanup and check again (the terminating threads
204 // should be gone)
205 NextSubTest();
206 snooze(500000); // give them time to terminate
207 CHK(manager.CleanupThreads() == B_OK);
208 CHK(manager.ThreadCount() == (niceThreads + evilThreads));
210 // Now do a shutdown and check again (the nice infinite threads
211 // should be gone)
212 NextSubTest();
213 CHK(manager.ShutdownThreads() == B_OK);
214 snooze(1000000); // give them time to quit nicely
215 CHK(manager.CleanupThreads() == B_OK);
216 CHK(manager.ThreadCount() == evilThreads);
219 // Now finally kill any remaining threads (which should rid us of
220 // the naughty infinite threads)
221 NextSubTest();
222 CHK(manager.KillThreads() == B_OK);
223 CHK(manager.ThreadCount() == 0);
225 #endif // !TEST_R5
228 void
229 RegistrarThreadManagerTest::ThreadLimitTest()
231 #ifdef TEST_R5
232 Outputf("(no tests performed for R5 version)\n");
233 #else
234 NextSubTest();
235 status_t err = B_OK;
236 RegistrarThreadManager manager;
237 CHK(fApplication && fApplication->InitCheck() == B_OK);
238 BMessenger managerMessenger(NULL, fApplication, &err);
239 // TODO: Do something about this...
240 if (err != B_OK) {
241 fprintf(stderr, "Fails because we try to init an Haiku BMessenger with a "
242 "BLooper from R5's libbe (more precisely a BTestApp living in libcppunit, "
243 "which is only linked against R5's libbe).\n");
245 CHK(err == B_OK && managerMessenger.IsValid());
247 const uint termThreads = 2;
249 // This test is only useful if the thread limit of the manager
250 // class is > kTermThreads
251 CHK(termThreads < RegistrarThreadManager::kThreadLimit);
253 // Launch some terminating threads
254 uint i;
255 for (i = 0; i < termThreads; i++) {
256 NextSubTest();
257 char name[1024];
258 sprintf(name, "terminating #%d", i);
259 RegistrarThread *thread = new TerminatingThread(name, B_NORMAL_PRIORITY, managerMessenger);
260 CHK(thread != NULL);
261 CHK(thread->InitCheck() == B_OK);
262 CHK(manager.LaunchThread(thread) == B_OK);
265 // Now fill up the manager with non-terminating threads
266 for (; i < RegistrarThreadManager::kThreadLimit; i++) {
267 NextSubTest();
268 char name[1024];
269 sprintf(name, "nice #%d", i);
270 RegistrarThread *thread = new WellBehavedInfiniteThread(name, B_NORMAL_PRIORITY, managerMessenger);
271 CHK(thread != NULL);
272 CHK(thread->InitCheck() == B_OK);
273 CHK(manager.LaunchThread(thread) == B_OK);
275 CHK(manager.ThreadCount() == RegistrarThreadManager::kThreadLimit);
277 // Now try to launch just one more...
278 NextSubTest();
280 char *name = "hopeless thread";
281 RegistrarThread *thread = new WellBehavedInfiniteThread(name, B_NORMAL_PRIORITY, managerMessenger);
282 CHK(thread != NULL);
283 CHK(thread->InitCheck() == B_OK);
284 CHK(manager.LaunchThread(thread) == B_NO_MORE_THREADS);
285 delete thread;
288 // Now wait a little bit for our terminating threads to quit,
289 // cleanup after them, and make sure we can now launch that
290 // many threads again
291 NextSubTest();
292 snooze(500000);
293 manager.CleanupThreads();
295 for (i = 0; i < termThreads; i++) {
296 NextSubTest();
297 char name[1024];
298 sprintf(name, "2nd round nice #%d", i);
299 RegistrarThread *thread = new TerminatingThread(name, B_NORMAL_PRIORITY, managerMessenger);
300 CHK(thread != NULL);
301 CHK(thread->InitCheck() == B_OK);
302 CHK(manager.LaunchThread(thread) == B_OK);
305 // Now try once more to launch just one more...
306 NextSubTest();
308 char *name = "hopeless thread";
309 RegistrarThread *thread = new WellBehavedInfiniteThread(name, B_NORMAL_PRIORITY, managerMessenger);
310 CHK(thread != NULL);
311 CHK(thread->InitCheck() == B_OK);
312 CHK(manager.LaunchThread(thread) == B_NO_MORE_THREADS);
313 delete thread;
316 // Cleanup
317 NextSubTest();
318 manager.ShutdownThreads();
319 snooze(500000);
321 #endif // !TEST_R5