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 /*****************************************************************************
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 */
40 /*****************************************************************************
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 * );
51 static int Stress ( vlc_object_t *, char const *,
52 vlc_value_t, vlc_value_t, void * );
53 static void * Dummy ( vlc_object_t * );
55 static int Signal ( vlc_object_t *, char const *,
56 vlc_value_t, vlc_value_t, void * );
58 /*****************************************************************************
60 *****************************************************************************/
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 );
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 )
86 var_Create( p_this, "honk", VLC_VAR_STRING | VLC_VAR_HASCHOICE );
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 );
96 var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
98 val.psz_string = "foo";
99 var_Set( p_this, "honk", val );
101 var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
103 val.psz_string = "blork";
104 var_Set( p_this, "honk", val );
106 var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
108 val.psz_string = "baz";
109 var_Change( p_this, "honk", VLC_VAR_DELCHOICE, &val, NULL );
111 var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
113 var_Change( p_this, "honk", VLC_VAR_GETLIST, &val, NULL );
114 for( i = 0 ; i < val.p_list->i_count ; i++ )
116 printf( "value %i: %s\n", i, val.p_list->p_values[i].psz_string );
118 var_Change( p_this, "honk", VLC_VAR_FREELIST, &val, NULL );
120 var_Destroy( p_this, "honk" );
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 )
133 vlc_object_t *pp_objects[10];
136 /* Allocate a few variables */
137 for( i = 0; i < 1000; i++ )
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 );
145 * Test #1: callback loop detection
147 printf( "Test #1: callback loop detection\n" );
149 printf( " - without boundary check (vlc should print an error)\n" );
151 var_Set( p_this, "blork-12", val );
153 printf( " - with boundary check\n" );
155 var_Set( p_this, "blork-12", val );
158 * Test #2: concurrent access
160 printf( "Test #2: concurrent access\n" );
162 printf( " - launch worker threads\n" );
164 for( i = 0; i < 10; i++ )
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 );
173 printf( " - kill worker threads\n" );
175 for( i = 0; i < 10; i++ )
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] );
184 for( i = 0; i < 1000; i++ )
186 sprintf( psz_var, "blork-%i", i );
187 var_DelCallback( p_this, psz_var, MyCallback, NULL );
188 var_Destroy( p_this, psz_var );
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 )
200 int i_var = 1 + atoi( psz_var + strlen("blork-") );
208 /* If we are requested to stop, then stop. */
209 if( i_var == newval.i_int )
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 );
221 /*****************************************************************************
222 * MyThread: used by callback-test, creates objects and then do nothing.
223 *****************************************************************************/
224 static void * MyThread( vlc_object_t *p_this )
228 vlc_object_t *p_parent = p_this->p_parent;
230 vlc_thread_ready( p_this );
234 while( !p_this->b_die )
236 int i = (int) (100.0 * rand() / (RAND_MAX));
238 sprintf( psz_var, "blork-%i", i );
240 var_Set( p_parent, psz_var, val );
242 /* This is quite heavy, but we only have 10 threads. Keep cool. */
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 )
255 vlc_object_t **pp_objects;
261 if( *newval.psz_string )
263 i_level = atoi( newval.psz_string );
268 else if( i_level > 200 )
270 /* It becomes quite dangerous above 150 */
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++ )
284 ppsz_name[i] = psz_blob + 20 * i;
287 pp_objects = malloc( MAXOBJ * i_level * sizeof(void*) );
292 printf( "Test #1: objects\n" );
294 printf( " - creating %i objects\n", MAXOBJ * i_level );
296 for( i = 0; i < MAXOBJ * i_level; i++ )
298 pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC );
301 printf( " - randomly looking up %i objects\n", MAXLOOK * i_level );
302 for( i = MAXLOOK * i_level; i--; )
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 );
309 printf( " - destroying the objects (LIFO)\n" );
310 for( i = MAXOBJ * i_level; i--; )
312 vlc_object_destroy( pp_objects[i] );
315 printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
318 * Test #2: integer variables
320 printf( "Test #2: integer variables\n" );
322 printf( " - creating %i integer variables\n", MAXVAR * i_level );
324 for( i = 0; i < MAXVAR * i_level; i++ )
326 sprintf( ppsz_name[i], "foo-%04i-bar-%04x", i, i * 11 );
327 var_Create( p_this, ppsz_name[i], VLC_VAR_INTEGER );
330 printf( " - randomly assigning %i values\n", MAXSET * i_level );
331 for( i = 0; i < MAXSET * i_level; i++ )
333 int v = (int) (MAXVAR * i_level * 1.0 * rand() / (RAND_MAX));
334 var_Set( p_this, ppsz_name[v], (vlc_value_t)i );
337 printf( " - destroying the variables\n" );
338 for( i = 0; i < MAXVAR * i_level; i++ )
340 var_Destroy( p_this, ppsz_name[i] );
343 printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
346 * Test #3: string variables
348 printf( "Test #3: string variables\n" );
350 printf( " - creating %i string variables\n", MAXVAR * i_level );
352 for( i = 0; i < MAXVAR * i_level; i++ )
354 sprintf( ppsz_name[i], "foo-%04i-bar-%04x", i, i * 11 );
355 var_Create( p_this, ppsz_name[i], VLC_VAR_STRING );
358 printf( " - randomly assigning %i values\n", MAXSET * i_level );
359 for( i = 0; i < MAXSET * i_level; i++ )
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] );
365 printf( " - destroying the variables\n" );
366 for( i = 0; i < MAXVAR * i_level; i++ )
368 var_Destroy( p_this, ppsz_name[i] );
371 printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
376 printf( "Test #4: threads\n" );
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++ )
383 pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC );
384 vlc_thread_create( pp_objects[i], "foo", Dummy, 0, VLC_TRUE );
387 printf( " - killing the threads (LIFO)\n" );
388 for( i = MAXTH * i_level; i--; )
390 pp_objects[i]->b_die = VLC_TRUE;
391 vlc_thread_join( pp_objects[i] );
392 vlc_object_destroy( pp_objects[i] );
395 printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
397 /* Free required data */
405 /*****************************************************************************
406 * Dummy: used by stress-test, creates objects and then do nothing.
407 *****************************************************************************/
408 static void * Dummy( vlc_object_t *p_this )
411 vlc_object_t *pp_objects[MAXOBJ/MAXTH];
413 for( i = 0; i < MAXOBJ/MAXTH; i++ )
415 pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC );
418 vlc_thread_ready( p_this );
420 while( !p_this->b_die )
425 for( i = MAXOBJ/MAXTH; i--; )
427 vlc_object_destroy( pp_objects[i] );
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 )
439 raise( atoi(newval.psz_string) );