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