]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/dde/linux26/examples/unittest/main.c
Inital import
[l4.git] / l4 / pkg / dde / linux26 / examples / unittest / main.c
1 /*
2  * \brief   DDE for Linux 2.6 Unit tests
3  * \author  Bjoern Doebel <doebel@os.inf.tu-dresden.de>
4  * \author  Christian Helmuth <ch12@os.inf.tu-dresden.de>
5  * \date    2007-05-12
6  */
7
8 #include <asm/current.h>
9
10 #include <linux/kernel.h>
11 #include <linux/completion.h>
12 #include <linux/init.h>
13 #include <linux/delay.h>
14 #include <linux/wait.h>
15 #include <linux/sched.h>
16 #include <linux/workqueue.h>
17 #include <linux/interrupt.h>
18 //#include <linux/kthread.h>
19
20 #include <l4/dde/dde.h>
21 #include <l4/dde/ddekit/initcall.h>
22 #include <l4/dde/linux26/dde26.h>
23
24 #include <l4/cunit/CUnit.h>
25 #include <l4/cunit/Basic.h>
26 #include <l4/util/parse_cmd.h>
27 #include <l4/util/util.h>
28 #include <l4/log/l4log.h>
29
30 /* We define 4 initcalls and see if these are executed
31  * in the beginning and in the right order. Expecations:
32  *
33  * - After running the init calls, _init_count == 4
34  * - {_foo, _bar, _bla, _blub}_count carry numbers from 0 through 3
35  *   giving their execution order. These need to be:
36  *   - _foo_count == 3
37  *   - _bar_count == 2
38  *   - _bla_count == 0
39  *   - _blub_count == 1
40  */
41 static unsigned _init_count = 0;
42 static unsigned _foo_count  = 0;
43 static unsigned _bar_count  = 0;
44 static unsigned _bla_count  = 0;
45 static unsigned _blub_count = 0;
46
47 /** Test checking whether the initcalls have been executed correctly. */
48 static int test_initcalls(void)
49 {
50         CU_ASSERT(_init_count == 4);
51         CU_ASSERT(_foo_count  == 3);
52         CU_ASSERT(_bar_count  == 2);
53         CU_ASSERT(_blub_count == 1);
54         CU_ASSERT(_bla_count  == 0);
55         return 0;
56 }
57
58
59 static void foo(void) 
60 {
61         _foo_count = _init_count++;
62 }
63 late_initcall(foo);
64
65 static void bar(void) 
66 {
67         _bar_count = _init_count++;
68 }
69 device_initcall(bar);
70
71 static void bla(void) 
72 {
73         _bla_count = _init_count++;
74 }
75 arch_initcall(bla);
76
77 static void blub(void) 
78 {
79         _blub_count = _init_count++;
80 }
81 subsys_initcall(blub);
82
83 /***********************************************************************
84  ** Test 1: Check whether the current() macro works.                  **
85  ***********************************************************************/
86 static int current_test(void)
87 {
88         struct task_struct *t = current;
89         CU_ASSERT(t != NULL);
90         return 0;
91 }
92
93
94 /***********************************************************************
95  ** Test 2: Getting complicated. Test startup of some kernel threads  **
96  **         and wait for them to finish using completions.            **
97  ***********************************************************************/
98 #define NUM_KTHREADS    5
99 static struct completion _kthread_completions_[NUM_KTHREADS];
100
101 static int kernel_thread_func(void *arg)
102 {
103         CU_ASSERT((int)arg >= 0);
104         CU_ASSERT((int)arg < NUM_KTHREADS);
105         CU_ASSERT(current != NULL);
106
107         /* do some work */
108         msleep(200);
109
110         complete_and_exit( &_kthread_completions_[(int)arg], 0 );
111         return 0;
112 }
113
114
115 static int kernel_thread_test(void)
116 {
117         int i;
118         
119         for (i=0; i < NUM_KTHREADS; i++) {
120                 int j;
121                 // initialize completion event
122                 init_completion(&_kthread_completions_[i]);
123                 // start kernel thread
124                 j = kernel_thread(kernel_thread_func, (void *)i, 0);
125                 CU_ASSERT(j > 0);
126         }
127
128         for (i=0; i < NUM_KTHREADS; i++) {
129                 // await completion
130                 wait_for_completion(&_kthread_completions_[i]);
131         }
132         CU_ASSERT(i==NUM_KTHREADS);
133
134         return 0;
135 }
136
137
138 /******************************************************************************
139  ** Test 3: Test kernel wait queues: start a thread incrementing wait_value, **
140  **         and  sleep until wait_value is larger than 6 for the first time. **
141  ******************************************************************************/
142 static DECLARE_WAIT_QUEUE_HEAD(_wq_head);
143 static unsigned wait_value = 0;
144 static struct completion wq_completion;
145
146 static int inc_func(void *arg)
147 {
148         int i = 0;
149
150         for (i=0; i<10; i++)
151         {
152                 ++wait_value;
153                 wake_up(&_wq_head);
154                 msleep(500);
155         }
156         CU_ASSERT(wait_value == 10);
157         CU_ASSERT(i == 10);
158         complete_and_exit(&wq_completion, 0);
159 }
160
161
162 static int wq_test(void)
163 {
164         int pid;
165
166         init_completion(&wq_completion);
167         // start a thread incrementing wait_value
168         pid = kernel_thread(inc_func, 0, 0);
169         CU_ASSERT(pid > 0);
170
171         // wait until wait_value > 6
172         wait_event(_wq_head, wait_value > 6);
173         CU_ASSERT(wait_value > 6);
174
175         // wait for inc_thread to exit
176         wait_for_completion(&wq_completion);
177         CU_ASSERT(wait_value == 10);
178
179         return 0;
180 }
181
182
183 /****************************************************************************
184  ** Test 4: Tasklets                                                       **
185  ****************************************************************************/
186 static unsigned _low_count = 0;
187 static unsigned _high_count = 0;
188
189 static void tasklet_low_func(unsigned long i)
190 {
191         ++_low_count;
192 }
193
194 static void tasklet_high_func(unsigned long i)
195 {
196         ++_high_count;
197 }
198
199 static DECLARE_TASKLET(low0, tasklet_low_func, 0);
200 static DECLARE_TASKLET(low1, tasklet_low_func, 1);
201 static DECLARE_TASKLET(low2, tasklet_low_func, 2);
202 static DECLARE_TASKLET_DISABLED(low3, tasklet_low_func, 3);
203
204 static DECLARE_TASKLET(hi0, tasklet_high_func, 10);
205 static DECLARE_TASKLET(hi1, tasklet_high_func, 11);
206 static DECLARE_TASKLET_DISABLED(hi2, tasklet_high_func, 12);
207
208
209 static int tasklet_test(void)
210 {
211         l4dde26_softirq_init();
212
213         // schedule tasklets 0-3, 3 disabled
214         tasklet_schedule(&low0);
215         tasklet_schedule(&low1);
216         tasklet_schedule(&low2);
217         tasklet_schedule(&low3);
218         msleep(500);
219
220         // 0-2 should have executed by now
221         CU_ASSERT(_low_count == 3);
222         tasklet_enable(&low3);
223         msleep(500);
224         // 3 should be ready, too
225         CU_ASSERT(_low_count == 4);
226         
227         // schedule hi and low tasklets, hi2 is disabled
228         tasklet_hi_schedule(&hi0);
229         tasklet_hi_schedule(&hi1);
230         tasklet_hi_schedule(&hi2);
231         tasklet_schedule(&low0);
232         tasklet_schedule(&low1);
233         tasklet_schedule(&low2);
234         msleep(500);
235         CU_ASSERT(_high_count == 2);
236         CU_ASSERT(_low_count  == 7);
237
238         // enable hi2
239         tasklet_enable(&hi2);
240         // schedule low3 2 times, should only run once
241         tasklet_schedule(&low3);
242         tasklet_schedule(&low3);
243         msleep(500);
244         CU_ASSERT(_high_count == 3);
245         CU_ASSERT(_low_count == 8);
246
247         return 0;
248 }
249
250
251 #if 0
252 /******************************************************************************
253  ** Test 5: Timers                                                           **
254  **                                                                          **
255  ** Schedule a periodic timer printing "tick" every second. Additionally,    **
256  ** schedule timers for 5, 10, 15, 20, and 25 seconds. Timer at 15s will     **
257  ** deactivate the 20s timer.                                                **
258  ******************************************************************************/
259
260 static struct timer_list _timer;
261 static struct timer_list _timer5;
262 static struct timer_list _timer10;
263 static struct timer_list _timer15;
264 static struct timer_list _timer20;
265 static struct timer_list _timer25;
266
267 static void tick_func(unsigned long d)
268 {
269         printk("tick (%ld)\n", jiffies);
270         _timer.expires = jiffies + HZ;
271         add_timer(&_timer);
272 }
273
274
275 static void timer_func(unsigned long d)
276 {
277         printk("timer_func: %lu\n", d);
278
279         if (d == 15) {
280                 printk("De-scheduling 20s timer.\n");
281                 del_timer(&_timer20);
282         }
283
284         if (timer_pending(&_timer20))
285                 printk("timer for 20s still pending.\n");
286         else
287                 printk("timer for 20s has been disabled.\n");
288 }
289
290
291 static void timer_test(void)
292 {
293         l4dde26_init_timers();
294
295         printk("BEGIN TIMER TEST\n");
296         printk("jiffies(%p): %ld, HZ(%p): %ld\n", &jiffies, jiffies, &HZ, HZ);
297
298         setup_timer(&_timer, tick_func, 0);
299         _timer.expires = jiffies + HZ;
300         add_timer(&_timer);
301
302         setup_timer(&_timer5, timer_func, 5);
303         _timer5.expires = jiffies + 5*HZ;
304         setup_timer(&_timer10, timer_func, 10); 
305         _timer10.expires = jiffies + 10*HZ;
306         setup_timer(&_timer15, timer_func, 15); 
307         _timer15.expires = jiffies + 15*HZ;
308         setup_timer(&_timer20, timer_func, 20); 
309         _timer20.expires = jiffies + 20*HZ;
310         setup_timer(&_timer25, timer_func, 25); 
311         _timer25.expires = jiffies + 25*HZ;
312
313         add_timer(&_timer5);
314         add_timer(&_timer10);
315         add_timer(&_timer15);
316         add_timer(&_timer20);
317         add_timer(&_timer25);
318
319         msleep(30000);
320         printk("END TIMER TEST\n");
321 }
322 #endif
323
324
325 /******************************
326  ** Test 6: Memory subsystem **
327  ******************************/
328
329 static void memory_kmem_cache_test(void)
330 {
331         struct kmem_cache *cache0 = NULL;
332         struct obj0
333         {
334                 unsigned foo;
335                 unsigned bar;
336         };
337         static struct obj0 *p0[1024];
338
339         struct kmem_cache *cache1 = NULL;
340         struct obj1
341         {
342                 char      foo[50];
343                 unsigned *bar;
344         };
345         static struct obj1 *p1[256];
346
347         CU_ASSERT(cache0 == NULL);
348         CU_ASSERT(cache1 == NULL);
349
350         cache0 = kmem_cache_create("obj0", sizeof(*p0[0]), 0, 0, 0);
351         cache1 = kmem_cache_create("obj1", sizeof(*p1[0]), 0, 0, 0);
352
353         CU_ASSERT(cache0 != NULL);
354         CU_ASSERT(cache1 != NULL);
355
356         unsigned i;
357         for (i = 0; i < 1024; ++i) {
358                 p0[i] = kmem_cache_alloc(cache0, i);
359                 CU_ASSERT(p0[i] != NULL);
360         }
361
362         for (i = 0; i < 256; ++i) {
363                 p1[i] = kmem_cache_alloc(cache1, i);
364                 CU_ASSERT(p1[i] != NULL);
365         }
366
367         for (i = 256; i > 0; --i)
368                 kmem_cache_free(cache1, p1[i-1]);
369
370         for (i = 1024; i > 0; --i)
371                 kmem_cache_free(cache0, p0[i-1]);
372
373         kmem_cache_destroy(cache1);
374         kmem_cache_destroy(cache0);
375 }
376
377
378 static void memory_page_alloc_test(void)
379 {
380         unsigned long p[4];
381         p[0] = __get_free_page(GFP_KERNEL);
382         p[1] = __get_free_pages(GFP_KERNEL, 1);
383         p[2] = __get_free_pages(GFP_KERNEL, 2);
384         p[3] = __get_free_pages(GFP_KERNEL, 3);
385
386         CU_ASSERT(p[0] != 0);
387         CU_ASSERT(p[1] != 0);
388         CU_ASSERT(p[2] != 0);
389         CU_ASSERT(p[3] != 0);
390
391         free_pages(p[0], 0);
392         free_pages(p[1], 1);
393         free_pages(p[2], 2);
394         free_pages(p[3], 3);
395 }
396
397
398 static void memory_kmalloc_test(void)
399 {
400         l4dde26_kmalloc_init();
401
402         const unsigned count = 33;
403         char *p[count];
404
405         unsigned i;
406         for (i = 0; i < count; ++i) {
407                 p[i] = kmalloc(32 + i*15, GFP_KERNEL);
408                 CU_ASSERT(p[i] != NULL);
409                 *p[i] = i;
410                 CU_ASSERT(*p[i] == i);
411         }
412
413         for (i = count; i > 0; --i)
414                 if (p[i-1]) kfree(p[i-1]);
415
416         for (i = 0; i < count; ++i) {
417                 p[i] = kmalloc(3000 + i*20, GFP_KERNEL);
418                 CU_ASSERT(p[i] != NULL);
419                 *p[i] = i;
420                 CU_ASSERT(*p[i] == i);
421         }
422
423         for (i = count; i > 0; --i)
424                 if (p[i-1]) kfree(p[i-1]);
425
426 }
427
428
429 static int memory_test(void)
430 {
431         if (1) memory_kmem_cache_test();
432         if (1) memory_page_alloc_test();
433         if (1) memory_kmalloc_test();
434         return 0;
435 }
436
437 #if 0
438 /****************************************************************************
439  ** Test 7: KThreads                                                       **
440  ****************************************************************************/
441 void kthread_test(void)
442 {
443 }
444
445
446 /****************************************************************************
447  ** Test 8: Work queues                                                    **
448  ****************************************************************************/
449 static void work_queue_func(void *data);
450 static void work_queue_func2(void *data);
451 static struct workqueue_struct *_wq;
452 static DECLARE_WORK(_wobj, work_queue_func, NULL);
453 static DECLARE_WORK(_wobj2, work_queue_func2, NULL);
454 static int wq_cnt = 0;
455
456 static void work_queue_func(void *data)
457 {
458         printk("Work queue function... Do some work here...\n");
459         if (++wq_cnt < 5)
460                 queue_work(_wq, &_wobj);
461 }
462
463
464 static void work_queue_func2(void *data)
465 {
466         printk("Work queue function 2... Do some work here...\n");
467         if (++wq_cnt < 5)
468                 schedule_work(&_wobj2);
469 }
470
471
472 static void work_queue_test(void)
473 {
474         int i;
475         printk("BEGIN WQ TEST\n");
476         _wq = create_workqueue("HelloWQ");
477         BUG_ON(_wq == NULL);
478         queue_work(_wq, &_wobj);
479         schedule_work(&_wobj2);
480         printk("END WQ TEST\n");
481 }
482
483
484 /****************************************************************************
485  ** Test 9: PCI                                                            **
486  ****************************************************************************/
487
488 void pci_test(void)
489 {
490         l4dde26_init_pci();
491 }
492
493
494 /*************************************************
495  ** Main routine (switch on desired tests here) **
496  *************************************************/
497
498 int main(int argc, const char **argv)
499 {
500         int test_current = 0;
501         int test_kernel_thread = 0;
502         int test_wait = 0;
503         int test_tasklet = 0;
504         int test_timer = 0;
505         int test_memory = 0;
506         int test_kthread = 0;
507         int test_work = 0;
508         int test_pci = 0;
509
510         if (parse_cmdline(&argc, &argv,
511                 'c', "current", "test current() function",
512                 PARSE_CMD_SWITCH, 1, &test_current,
513                 'k', "kernel-thread", "test startup of kernel threads",
514                 PARSE_CMD_SWITCH, 1, &test_kernel_thread,
515                 'w', "waitqueue", "test wait queues",
516                 PARSE_CMD_SWITCH, 1, &test_wait,
517                 't', "tasklet", "test tasklets",
518                 PARSE_CMD_SWITCH, 1, &test_tasklet,
519                 'T', "timer", "test timers",
520                 PARSE_CMD_SWITCH, 1, &test_timer,
521                 'm', "memory", "test memory management",
522                 PARSE_CMD_SWITCH, 1, &test_memory,
523                 'K', "kthread", "test kthreads",
524                 PARSE_CMD_SWITCH, 1, &test_kthread,
525                 'W', "workqueue", "test work queues",
526                 PARSE_CMD_SWITCH, 1, &test_work,
527                 'p', "pci", "test PCI stuff",
528                 PARSE_CMD_SWITCH, 1, &test_pci,
529                 0, 0))
530                 return 1;
531
532         LOG("DDEKit test. Carrying out tests:");
533         LOGd(test_current, "\t* current()");
534         LOGd(test_kernel_thread, "\t* kernel_thread()");
535         LOGd(test_wait, "\t* wait queues");
536         LOGd(test_tasklet, "\t* tasklets");
537         LOGd(test_timer, "\t* timers");
538         LOGd(test_memory, "\t* memory management");
539         LOGd(test_kthread, "\t* kthreads");
540         LOGd(test_work, "\t* work queues");
541         LOGd(test_pci, "\t* PCI subsystem");
542
543         l4dde26_init();
544         l4dde26_process_init();
545         l4dde26_do_initcalls();
546
547         if (test_current) current_test();
548         if (test_kernel_thread) kernel_thread_test();
549         if (test_wait) wq_test();
550         if (test_tasklet) tasklet_test();
551         if (test_timer) timer_test();
552         if (test_memory) memory_test();
553 /*      if (1) kthread_test(); */
554         if (test_work) work_queue_test();
555         if (test_pci) pci_test();
556
557         return 0;
558 }
559 #endif
560
561 static int dde26_ts_init(void)
562 {
563         l4dde26_init();
564         l4dde26_process_init();
565         l4dde26_do_initcalls();
566         return 0;
567 }
568
569
570 static int dde26_ts_cleanup(void)
571 {
572         return 0;
573 }
574
575
576 int main(int argc, char **argv)
577 {
578         CU_pSuite dde_testsuite = NULL;
579         
580         int err = CU_initialize_registry();
581         if (err == CUE_SUCCESS)
582                 printk("Initialized CUnit registry.\n");
583         else {
584                 printk("Could not initialize CUnit registry.\n");
585                 return -1;
586         }
587
588         dde_testsuite = CU_add_suite("DDE2.6 test suite", dde26_ts_init, dde26_ts_cleanup);
589         if (dde_testsuite)
590                 printk("Added DDE2.6 test suite.\n");
591         else {
592                 printk("Could not add DDE2.6 test suite.\n");
593                 return -2;
594         }
595
596         CU_ADD_TEST(dde_testsuite, test_initcalls);
597         CU_ADD_TEST(dde_testsuite, current_test);
598         CU_ADD_TEST(dde_testsuite, kernel_thread_test);
599         CU_ADD_TEST(dde_testsuite, wq_test);
600         CU_ADD_TEST(dde_testsuite, tasklet_test);
601         CU_ADD_TEST(dde_testsuite, memory_test);
602
603         CU_basic_set_mode(CU_BRM_VERBOSE);
604         CU_basic_run_tests();
605
606         CU_cleanup_registry();
607
608         l4_sleep_forever();
609
610         return 0;
611 }