]> git.sesse.net Git - vlc/blob - modules/misc/testsuite/test4.c
Removes trailing spaces. Removes tabs.
[vlc] / modules / misc / testsuite / test4.c
1 /*****************************************************************************
2  * test4.c : Miscellaneous stress tests module for vlc
3  *****************************************************************************
4  * Copyright (C) 2002 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <vlc/vlc.h>
28
29 #include <signal.h>
30
31 /*****************************************************************************
32  * Defines
33  *****************************************************************************/
34 #define MAXVAR        50                    /* Number of variables to create */
35 #define MAXSET      2000                       /* Number of variables to set */
36 #define MAXOBJ      1000                      /* Number of objects to create */
37 #define MAXLOOK    10000                      /* Number of objects to lookup */
38 #define MAXTH          4                       /* Number of threads to spawn */
39
40 /*****************************************************************************
41  * Local prototypes.
42  *****************************************************************************/
43 static int    Foo       ( vlc_object_t *, char const *,
44                           vlc_value_t, vlc_value_t, void * );
45 static int    Callback  ( vlc_object_t *, char const *,
46                           vlc_value_t, vlc_value_t, void * );
47 static int    MyCallback( vlc_object_t *, char const *,
48                           vlc_value_t, vlc_value_t, void * );
49 static void * MyThread  ( vlc_object_t * );
50
51 static int    Stress    ( vlc_object_t *, char const *,
52                           vlc_value_t, vlc_value_t, void * );
53 static void * Dummy     ( vlc_object_t * );
54
55 static int    Signal    ( vlc_object_t *, char const *,
56                           vlc_value_t, vlc_value_t, void * );
57
58 /*****************************************************************************
59  * Module descriptor.
60  *****************************************************************************/
61 vlc_module_begin();
62     set_description( _("Miscellaneous stress tests") );
63     var_Create( p_module->p_libvlc, "foo-test",
64                 VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
65     var_AddCallback( p_module->p_libvlc, "foo-test", Foo, NULL );
66     var_Create( p_module->p_libvlc, "callback-test",
67                 VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
68     var_AddCallback( p_module->p_libvlc, "callback-test", Callback, NULL );
69     var_Create( p_module->p_libvlc, "stress-test",
70                 VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
71     var_AddCallback( p_module->p_libvlc, "stress-test", Stress, NULL );
72     var_Create( p_module->p_libvlc, "signal",
73                 VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
74     var_AddCallback( p_module->p_libvlc, "signal", Signal, NULL );
75 vlc_module_end();
76
77 /*****************************************************************************
78  * Foo: put anything here
79  *****************************************************************************/
80 static int Foo( vlc_object_t *p_this, char const *psz_cmd,
81                 vlc_value_t oldval, vlc_value_t newval, void *p_data )
82 {
83     vlc_value_t val;
84     int i;
85
86     var_Create( p_this, "honk", VLC_VAR_STRING | VLC_VAR_HASCHOICE );
87
88     val.psz_string = "foo";
89     var_Change( p_this, "honk", VLC_VAR_ADDCHOICE, &val, NULL );
90     val.psz_string = "bar";
91     var_Change( p_this, "honk", VLC_VAR_ADDCHOICE, &val, NULL );
92     val.psz_string = "baz";
93     var_Change( p_this, "honk", VLC_VAR_ADDCHOICE, &val, NULL );
94     var_Change( p_this, "honk", VLC_VAR_SETDEFAULT, &val, NULL );
95
96     var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
97
98     val.psz_string = "foo";
99     var_Set( p_this, "honk", val );
100
101     var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
102
103     val.psz_string = "blork";
104     var_Set( p_this, "honk", val );
105
106     var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
107
108     val.psz_string = "baz";
109     var_Change( p_this, "honk", VLC_VAR_DELCHOICE, &val, NULL );
110
111     var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
112
113     var_Change( p_this, "honk", VLC_VAR_GETLIST, &val, NULL );
114     for( i = 0 ; i < val.p_list->i_count ; i++ )
115     {
116         printf( "value %i: %s\n", i, val.p_list->p_values[i].psz_string );
117     }
118     var_Change( p_this, "honk", VLC_VAR_FREELIST, &val, NULL );
119
120     var_Destroy( p_this, "honk" );
121
122     return VLC_SUCCESS;
123 }
124
125 /*****************************************************************************
126  * Callback: test callback functions
127  *****************************************************************************/
128 static int Callback( vlc_object_t *p_this, char const *psz_cmd,
129                      vlc_value_t oldval, vlc_value_t newval, void *p_data )
130 {
131     int i;
132     char psz_var[20];
133     vlc_object_t *pp_objects[10];
134     vlc_value_t val;
135
136     /* Allocate a few variables */
137     for( i = 0; i < 1000; i++ )
138     {
139         sprintf( psz_var, "blork-%i", i );
140         var_Create( p_this, psz_var, VLC_VAR_INTEGER );
141         var_AddCallback( p_this, psz_var, MyCallback, NULL );
142     }
143
144     /*
145      *  Test #1: callback loop detection
146      */
147     printf( "Test #1: callback loop detection\n" );
148
149     printf( " - without boundary check (vlc should print an error)\n" );
150     val.i_int = 1234567;
151     var_Set( p_this, "blork-12", val );
152
153     printf( " - with boundary check\n" );
154     val.i_int = 12;
155     var_Set( p_this, "blork-12", val );
156
157     /*
158      *  Test #2: concurrent access
159      */
160     printf( "Test #2: concurrent access\n" );
161
162     printf( " - launch worker threads\n" );
163
164     for( i = 0; i < 10; i++ )
165     {
166         pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC );
167         vlc_object_attach( pp_objects[i], p_this );
168         vlc_thread_create( pp_objects[i], "foo", MyThread, 0, VLC_TRUE );
169     }
170
171     msleep( 3000000 );
172
173     printf( " - kill worker threads\n" );
174
175     for( i = 0; i < 10; i++ )
176     {
177         vlc_object_kill( pp_objects[i] );
178         vlc_thread_join( pp_objects[i] );
179         vlc_object_detach( pp_objects[i] );
180         vlc_object_destroy( pp_objects[i] );
181     }
182
183     /* Clean our mess */
184     for( i = 0; i < 1000; i++ )
185     {
186         sprintf( psz_var, "blork-%i", i );
187         var_DelCallback( p_this, psz_var, MyCallback, NULL );
188         var_Destroy( p_this, psz_var );
189     }
190
191     return VLC_SUCCESS;
192 }
193
194 /*****************************************************************************
195  * MyCallback: used by callback-test
196  *****************************************************************************/
197 static int MyCallback( vlc_object_t *p_this, char const *psz_var,
198                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
199 {
200     int i_var = 1 + atoi( psz_var + strlen("blork-") );
201     char psz_newvar[20];
202
203     if( i_var == 1000 )
204     {
205         i_var = 0;
206     }
207
208     /* If we are requested to stop, then stop. */
209     if( i_var == newval.i_int )
210     {
211         return VLC_SUCCESS;
212     }
213
214     /* If we're the blork-3 callback, set blork-4, and so on. */
215     sprintf( psz_newvar, "blork-%i", i_var );
216     var_Set( p_this, psz_newvar, newval );
217
218     return VLC_SUCCESS;
219 }
220
221 /*****************************************************************************
222  * MyThread: used by callback-test, creates objects and then do nothing.
223  *****************************************************************************/
224 static void * MyThread( vlc_object_t *p_this )
225 {
226     char psz_var[20];
227     vlc_value_t val;
228     vlc_object_t *p_parent = p_this->p_parent;
229
230     vlc_thread_ready( p_this );
231
232     val.i_int = 42;
233
234     while( !p_this->b_die )
235     {
236         int i = (int) (100.0 * rand() / (RAND_MAX));
237
238         sprintf( psz_var, "blork-%i", i );
239         val.i_int = i + 200;
240         var_Set( p_parent, psz_var, val );
241
242         /* This is quite heavy, but we only have 10 threads. Keep cool. */
243         msleep( 1000 );
244     }
245
246     return NULL;
247 }
248
249 /*****************************************************************************
250  * Stress: perform various stress tests
251  *****************************************************************************/
252 static int Stress( vlc_object_t *p_this, char const *psz_cmd,
253                    vlc_value_t oldval, vlc_value_t newval, void *p_data )
254 {
255     vlc_object_t **pp_objects;
256     mtime_t start;
257     char ** ppsz_name;
258     char *  psz_blob;
259     int     i, i_level;
260
261     if( *newval.psz_string )
262     {
263         i_level = atoi( newval.psz_string );
264         if( i_level <= 0 )
265         {
266             i_level = 1;
267         }
268         else if( i_level > 200 )
269         {
270             /* It becomes quite dangerous above 150 */
271             i_level = 200;
272         }
273     }
274     else
275     {
276         i_level = 10;
277     }
278
279     /* Allocate required data */
280     ppsz_name = malloc( MAXVAR * i_level * sizeof(char*) );
281     psz_blob = malloc( 20 * MAXVAR * i_level * sizeof(char) );
282     for( i = 0; i < MAXVAR * i_level; i++ )
283     {
284         ppsz_name[i] = psz_blob + 20 * i;
285     }
286
287     pp_objects = malloc( MAXOBJ * i_level * sizeof(void*) );
288
289     /*
290      *  Test #1: objects
291      */
292     printf( "Test #1: objects\n" );
293
294     printf( " - creating %i objects\n", MAXOBJ * i_level );
295     start = mdate();
296     for( i = 0; i < MAXOBJ * i_level; i++ )
297     {
298         pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC );
299     }
300
301     printf( " - randomly looking up %i objects\n", MAXLOOK * i_level );
302     for( i = MAXLOOK * i_level; i--; )
303     {
304         int id = (int) (MAXOBJ * i_level * 1.0 * rand() / (RAND_MAX));
305         vlc_object_get( p_this, pp_objects[id]->i_object_id );
306         vlc_object_release( p_this );
307     }
308
309     printf( " - destroying the objects (LIFO)\n" );
310     for( i = MAXOBJ * i_level; i--; )
311     {
312         vlc_object_destroy( pp_objects[i] );
313     }
314
315     printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
316
317     /*
318      *  Test #2: integer variables
319      */
320     printf( "Test #2: integer variables\n" );
321
322     printf( " - creating %i integer variables\n", MAXVAR * i_level );
323     start = mdate();
324     for( i = 0; i < MAXVAR * i_level; i++ )
325     {
326         sprintf( ppsz_name[i], "foo-%04i-bar-%04x", i, i * 11 );
327         var_Create( p_this, ppsz_name[i], VLC_VAR_INTEGER );
328     }
329
330     printf( " - randomly assigning %i values\n", MAXSET * i_level );
331     for( i = 0; i < MAXSET * i_level; i++ )
332     {
333         int v = (int) (MAXVAR * i_level * 1.0 * rand() / (RAND_MAX));
334         var_Set( p_this, ppsz_name[v], (vlc_value_t)i );
335     }
336
337     printf( " - destroying the variables\n" );
338     for( i = 0; i < MAXVAR * i_level; i++ )
339     {
340         var_Destroy( p_this, ppsz_name[i] );
341     }
342
343     printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
344
345     /*
346      *  Test #3: string variables
347      */
348     printf( "Test #3: string variables\n" );
349
350     printf( " - creating %i string variables\n", MAXVAR * i_level );
351     start = mdate();
352     for( i = 0; i < MAXVAR * i_level; i++ )
353     {
354         sprintf( ppsz_name[i], "foo-%04i-bar-%04x", i, i * 11 );
355         var_Create( p_this, ppsz_name[i], VLC_VAR_STRING );
356     }
357
358     printf( " - randomly assigning %i values\n", MAXSET * i_level );
359     for( i = 0; i < MAXSET * i_level; i++ )
360     {
361         int v = (int) (MAXVAR * i_level * 1.0 * rand() / (RAND_MAX));
362         var_Set( p_this, ppsz_name[v], (vlc_value_t)ppsz_name[v] );
363     }
364
365     printf( " - destroying the variables\n" );
366     for( i = 0; i < MAXVAR * i_level; i++ )
367     {
368         var_Destroy( p_this, ppsz_name[i] );
369     }
370
371     printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
372
373     /*
374      *  Test #4: threads
375      */
376     printf( "Test #4: threads\n" );
377     start = mdate();
378
379     printf( " - spawning %i threads that will each create %i objects\n",
380             MAXTH * i_level, MAXOBJ/MAXTH );
381     for( i = 0; i < MAXTH * i_level; i++ )
382     {
383         pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC );
384         vlc_thread_create( pp_objects[i], "foo", Dummy, 0, VLC_TRUE );
385     }
386
387     printf( " - killing the threads (LIFO)\n" );
388     for( i = MAXTH * i_level; i--; )
389     {
390         pp_objects[i]->b_die = VLC_TRUE;
391         vlc_thread_join( pp_objects[i] );
392         vlc_object_destroy( pp_objects[i] );
393     }
394
395     printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
396
397     /* Free required data */
398     free( pp_objects );
399     free( psz_blob );
400     free( ppsz_name );
401
402     return VLC_SUCCESS;
403 }
404
405 /*****************************************************************************
406  * Dummy: used by stress-test, creates objects and then do nothing.
407  *****************************************************************************/
408 static void * Dummy( vlc_object_t *p_this )
409 {
410     int i;
411     vlc_object_t *pp_objects[MAXOBJ/MAXTH];
412
413     for( i = 0; i < MAXOBJ/MAXTH; i++ )
414     {
415         pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC );
416     }
417
418     vlc_thread_ready( p_this );
419
420     while( !p_this->b_die )
421     {
422         msleep( 10000 );
423     }
424
425     for( i = MAXOBJ/MAXTH; i--; )
426     {
427         vlc_object_destroy( pp_objects[i] );
428     }
429
430     return NULL;
431 }
432
433 /*****************************************************************************
434  * Signal: send a signal to the current thread.
435  *****************************************************************************/
436 static int Signal( vlc_object_t *p_this, char const *psz_cmd,
437                    vlc_value_t oldval, vlc_value_t newval, void *p_data )
438 {
439     raise( atoi(newval.psz_string) );
440     return VLC_SUCCESS;
441 }