1 /*****************************************************************************
2 * test4.c : Miscellaneous stress tests module for vlc
3 *****************************************************************************
4 * Copyright (C) 2002 the VideoLAN team
7 * Authors: Samuel Hocevar <sam@zoy.org>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
36 /*****************************************************************************
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 */
45 /*****************************************************************************
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 * );
56 static int Stress ( vlc_object_t *, char const *,
57 vlc_value_t, vlc_value_t, void * );
58 static void * Dummy ( vlc_object_t * );
60 static int Signal ( vlc_object_t *, char const *,
61 vlc_value_t, vlc_value_t, void * );
63 /*****************************************************************************
65 *****************************************************************************/
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 );
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 )
91 var_Create( p_this, "honk", VLC_VAR_STRING | VLC_VAR_HASCHOICE );
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 );
101 var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
102 free( val.psz_string );
104 val.psz_string = "foo";
105 var_Set( p_this, "honk", val );
107 var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
108 free( val.psz_string );
110 val.psz_string = "blork";
111 var_Set( p_this, "honk", val );
113 var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
114 free( val.psz_string );
116 val.psz_string = "baz";
117 var_Change( p_this, "honk", VLC_VAR_DELCHOICE, &val, NULL );
119 var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
121 var_Change( p_this, "honk", VLC_VAR_GETLIST, &val, NULL );
122 for( i = 0 ; i < val.p_list->i_count ; i++ )
124 printf( "value %i: %s\n", i, val.p_list->p_values[i].psz_string );
126 var_FreeList( &val, NULL );
128 var_Destroy( p_this, "honk" );
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 )
141 vlc_object_t *pp_objects[10];
144 /* Allocate a few variables */
145 for( i = 0; i < 1000; i++ )
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 );
153 * Test #1: callback loop detection
155 printf( "Test #1: callback loop detection\n" );
157 printf( " - without boundary check (vlc should print an error)\n" );
159 var_Set( p_this, "blork-12", val );
161 printf( " - with boundary check\n" );
163 var_Set( p_this, "blork-12", val );
166 * Test #2: concurrent access
168 printf( "Test #2: concurrent access\n" );
170 printf( " - launch worker threads\n" );
172 for( i = 0; i < 10; i++ )
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 );
181 printf( " - kill worker threads\n" );
183 for( i = 0; i < 10; i++ )
185 vlc_object_kill( pp_objects[i] );
186 vlc_thread_join( pp_objects[i] );
187 vlc_object_release( pp_objects[i] );
191 for( i = 0; i < 1000; i++ )
193 sprintf( psz_var, "blork-%i", i );
194 var_DelCallback( p_this, psz_var, MyCallback, NULL );
195 var_Destroy( p_this, psz_var );
201 /*****************************************************************************
202 * MyCallback: used by callback-test
203 *****************************************************************************/
204 static int MyCallback( vlc_object_t *p_this, char const *psz_var,
205 vlc_value_t oldval, vlc_value_t newval, void *p_data )
207 int i_var = 1 + atoi( psz_var + strlen("blork-") );
215 /* If we are requested to stop, then stop. */
216 if( i_var == newval.i_int )
221 /* If we're the blork-3 callback, set blork-4, and so on. */
222 sprintf( psz_newvar, "blork-%i", i_var );
223 var_Set( p_this, psz_newvar, newval );
228 /*****************************************************************************
229 * MyThread: used by callback-test, creates objects and then do nothing.
230 *****************************************************************************/
231 static void * MyThread( vlc_object_t *p_this )
235 vlc_object_t *p_parent = p_this->p_parent;
237 vlc_thread_ready( p_this );
241 while( vlc_object_alive (p_this) )
243 int i = (int) (100.0 * rand() / (RAND_MAX));
244 /* FIXME: not thread-safe */
246 sprintf( psz_var, "blork-%i", i );
248 int canc = vlc_savecancel ();
249 var_Set( p_parent, psz_var, val );
250 vlc_restorecancel (canc);
252 /* This is quite heavy, but we only have 10 threads. Keep cool. */
259 /*****************************************************************************
260 * Stress: perform various stress tests
261 *****************************************************************************/
262 static int Stress( vlc_object_t *p_this, char const *psz_cmd,
263 vlc_value_t oldval, vlc_value_t newval, void *p_data )
265 vlc_object_t **pp_objects;
271 if( *newval.psz_string )
273 i_level = atoi( newval.psz_string );
278 else if( i_level > 200 )
280 /* It becomes quite dangerous above 150 */
289 /* Allocate required data */
290 ppsz_name = malloc( MAXVAR * i_level * sizeof(char*) );
291 psz_blob = malloc( 20 * MAXVAR * i_level );
292 for( i = 0; i < MAXVAR * i_level; i++ )
294 ppsz_name[i] = psz_blob + 20 * i;
297 pp_objects = malloc( MAXOBJ * i_level * sizeof(void*) );
302 printf( "Test #1: objects\n" );
304 printf( " - creating %i objects\n", MAXOBJ * i_level );
306 for( i = 0; i < MAXOBJ * i_level; i++ )
308 pp_objects[i] = vlc_object_create( p_this, sizeof( vlc_object_t ) );
311 printf( " - randomly looking up %i objects\n", MAXLOOK * i_level );
312 for( i = MAXLOOK * i_level; i--; )
314 int id = (int) (MAXOBJ * i_level * 1.0 * rand() / (RAND_MAX));
315 vlc_object_get( pp_objects[id]->i_object_id );
316 vlc_object_release( p_this );
319 printf( " - destroying the objects (LIFO)\n" );
320 for( i = MAXOBJ * i_level; i--; )
322 vlc_object_release( pp_objects[i] );
325 printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
328 * Test #2: integer variables
330 printf( "Test #2: integer variables\n" );
332 printf( " - creating %i integer variables\n", MAXVAR * i_level );
334 for( i = 0; i < MAXVAR * i_level; i++ )
336 sprintf( ppsz_name[i], "foo-%04i-bar-%04x", i, i * 11 );
337 var_Create( p_this, ppsz_name[i], VLC_VAR_INTEGER );
340 printf( " - randomly assigning %i values\n", MAXSET * i_level );
341 for( i = 0; i < MAXSET * i_level; i++ )
343 int v = (int) (MAXVAR * i_level * 1.0 * rand() / (RAND_MAX));
344 var_Set( p_this, ppsz_name[v], (vlc_value_t)i );
347 printf( " - destroying the variables\n" );
348 for( i = 0; i < MAXVAR * i_level; i++ )
350 var_Destroy( p_this, ppsz_name[i] );
353 printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
356 * Test #3: string variables
358 printf( "Test #3: string variables\n" );
360 printf( " - creating %i string variables\n", MAXVAR * i_level );
362 for( i = 0; i < MAXVAR * i_level; i++ )
364 sprintf( ppsz_name[i], "foo-%04i-bar-%04x", i, i * 11 );
365 var_Create( p_this, ppsz_name[i], VLC_VAR_STRING );
368 printf( " - randomly assigning %i values\n", MAXSET * i_level );
369 for( i = 0; i < MAXSET * i_level; i++ )
371 int v = (int) (MAXVAR * i_level * 1.0 * rand() / (RAND_MAX));
372 var_Set( p_this, ppsz_name[v], (vlc_value_t)ppsz_name[v] );
375 printf( " - destroying the variables\n" );
376 for( i = 0; i < MAXVAR * i_level; i++ )
378 var_Destroy( p_this, ppsz_name[i] );
381 printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
386 printf( "Test #4: threads\n" );
389 printf( " - spawning %i threads that will each create %i objects\n",
390 MAXTH * i_level, MAXOBJ/MAXTH );
391 for( i = 0; i < MAXTH * i_level; i++ )
393 pp_objects[i] = vlc_object_create( p_this, sizeof( vlc_object_t ) );
394 vlc_thread_create( pp_objects[i], "foo", Dummy, 0, true );
397 printf( " - killing the threads (LIFO)\n" );
398 for( i = MAXTH * i_level; i--; )
400 pp_objects[i]->b_die = true;
401 vlc_thread_join( pp_objects[i] );
402 vlc_object_release( pp_objects[i] );
405 printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
407 /* Free required data */
415 /*****************************************************************************
416 * Dummy: used by stress-test, creates objects and then do nothing.
417 *****************************************************************************/
418 static void * Dummy( vlc_object_t *p_this )
421 vlc_object_t *pp_objects[MAXOBJ/MAXTH];
423 for( i = 0; i < MAXOBJ/MAXTH; i++ )
425 pp_objects[i] = vlc_object_create( p_this, sizeof( vlc_object_t ) );
428 vlc_thread_ready( p_this );
430 while( vlc_object_alive (p_this) )
435 for( i = MAXOBJ/MAXTH; i--; )
437 vlc_object_release( pp_objects[i] );
443 /*****************************************************************************
444 * Signal: send a signal to the current thread.
445 *****************************************************************************/
446 static int Signal( vlc_object_t *p_this, char const *psz_cmd,
447 vlc_value_t oldval, vlc_value_t newval, void *p_data )
449 raise( atoi(newval.psz_string) );