1 /*****************************************************************************
2 * test4.c : Miscellaneous stress tests module for vlc
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: test4.c,v 1.5 2002/12/07 15:25:26 gbazin Exp $
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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 /*****************************************************************************
34 *****************************************************************************/
35 #define MAXVAR 50 /* Number of variables to create */
36 #define MAXSET 2000 /* Number of variables to set */
37 #define MAXOBJ 1000 /* Number of objects to create */
38 #define MAXLOOK 10000 /* Number of objects to lookup */
39 #define MAXTH 4 /* Number of threads to spawn */
41 /*****************************************************************************
43 *****************************************************************************/
44 static int Foo ( vlc_object_t *, char const *,
45 vlc_value_t, vlc_value_t, void * );
46 static int Callback ( vlc_object_t *, char const *,
47 vlc_value_t, vlc_value_t, void * );
48 static int MyCallback( vlc_object_t *, char const *,
49 vlc_value_t, vlc_value_t, void * );
50 static void * MyThread ( vlc_object_t * );
52 static int Stress ( vlc_object_t *, char const *,
53 vlc_value_t, vlc_value_t, void * );
54 static void * Dummy ( vlc_object_t * );
56 static int Signal ( vlc_object_t *, char const *,
57 vlc_value_t, vlc_value_t, void * );
59 /*****************************************************************************
61 *****************************************************************************/
63 set_description( _("Miscellaneous stress tests") );
64 var_Create( p_module->p_libvlc, "foo-test",
65 VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
66 var_AddCallback( p_module->p_libvlc, "foo-test", Foo, NULL );
67 var_Create( p_module->p_libvlc, "callback-test",
68 VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
69 var_AddCallback( p_module->p_libvlc, "callback-test", Callback, NULL );
70 var_Create( p_module->p_libvlc, "stress-test",
71 VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
72 var_AddCallback( p_module->p_libvlc, "stress-test", Stress, NULL );
73 var_Create( p_module->p_libvlc, "signal",
74 VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
75 var_AddCallback( p_module->p_libvlc, "signal", Signal, NULL );
78 /*****************************************************************************
79 * Foo: put anything here
80 *****************************************************************************/
81 static int Foo( vlc_object_t *p_this, char const *psz_cmd,
82 vlc_value_t oldval, vlc_value_t newval, void *p_data )
88 var_Create( p_this, "honk", VLC_VAR_STRING | VLC_VAR_HASCHOICE );
90 val.psz_string = "foo";
91 var_Change( p_this, "honk", VLC_VAR_ADDCHOICE, &val );
92 val.psz_string = "bar";
93 var_Change( p_this, "honk", VLC_VAR_ADDCHOICE, &val );
94 val.psz_string = "baz";
95 var_Change( p_this, "honk", VLC_VAR_ADDCHOICE, &val );
96 var_Change( p_this, "honk", VLC_VAR_SETDEFAULT, &val );
98 var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
100 val.psz_string = "foo";
101 var_Set( p_this, "honk", val );
103 var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
105 val.psz_string = "blork";
106 var_Set( p_this, "honk", val );
108 var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
110 val.psz_string = "baz";
111 var_Change( p_this, "honk", VLC_VAR_DELCHOICE, &val );
113 var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
115 var_Change( p_this, "honk", VLC_VAR_GETLIST, &val );
116 i_vals = ((vlc_value_t*)val.p_address)[0].i_int;
117 p_vals = &((vlc_value_t*)val.p_address)[1];
118 for( i = 0 ; i < i_vals ; i++ )
120 printf( "value %i: %s\n", i, p_vals[i].psz_string );
122 var_Change( p_this, "honk", VLC_VAR_FREELIST, &val );
124 var_Destroy( p_this, "honk" );
129 /*****************************************************************************
130 * Callback: test callback functions
131 *****************************************************************************/
132 static int Callback( vlc_object_t *p_this, char const *psz_cmd,
133 vlc_value_t oldval, vlc_value_t newval, void *p_data )
137 vlc_object_t *pp_objects[10];
140 /* Allocate a few variables */
141 for( i = 0; i < 1000; i++ )
143 sprintf( psz_var, "blork-%i", i );
144 var_Create( p_this, psz_var, VLC_VAR_INTEGER );
145 var_AddCallback( p_this, psz_var, MyCallback, NULL );
149 * Test #1: callback loop detection
151 printf( "Test #1: callback loop detection\n" );
153 printf( " - without boundary check (vlc should print an error)\n" );
155 var_Set( p_this, "blork-12", val );
157 printf( " - with boundary check\n" );
159 var_Set( p_this, "blork-12", val );
162 * Test #2: concurrent access
164 printf( "Test #2: concurrent access\n" );
166 printf( " - launch worker threads\n" );
168 for( i = 0; i < 10; i++ )
170 pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC );
171 vlc_object_attach( pp_objects[i], p_this );
172 vlc_thread_create( pp_objects[i], "foo", MyThread, 0, VLC_TRUE );
177 printf( " - kill worker threads\n" );
179 for( i = 0; i < 10; i++ )
181 pp_objects[i]->b_die = VLC_TRUE;
182 vlc_thread_join( pp_objects[i] );
183 vlc_object_detach( pp_objects[i] );
184 vlc_object_destroy( pp_objects[i] );
188 for( i = 0; i < 1000; i++ )
190 sprintf( psz_var, "blork-%i", i );
191 var_DelCallback( p_this, psz_var, MyCallback, NULL );
192 var_Destroy( p_this, psz_var );
198 /*****************************************************************************
199 * MyCallback: used by callback-test
200 *****************************************************************************/
201 static int MyCallback( vlc_object_t *p_this, char const *psz_var,
202 vlc_value_t oldval, vlc_value_t newval, void *p_data )
204 int i_var = 1 + atoi( psz_var + strlen("blork-") );
212 /* If we are requested to stop, then stop. */
213 if( i_var == newval.i_int )
218 /* If we're the blork-3 callback, set blork-4, and so on. */
219 sprintf( psz_newvar, "blork-%i", i_var );
220 var_Set( p_this, psz_newvar, newval );
225 /*****************************************************************************
226 * MyThread: used by callback-test, creates objects and then do nothing.
227 *****************************************************************************/
228 static void * MyThread( vlc_object_t *p_this )
232 vlc_object_t *p_parent = p_this->p_parent;
234 vlc_thread_ready( p_this );
238 while( !p_this->b_die )
240 int i = (int) (100.0 * rand() / (RAND_MAX));
242 sprintf( psz_var, "blork-%i", i );
244 var_Set( p_parent, psz_var, val );
246 /* This is quite heavy, but we only have 10 threads. Keep cool. */
253 /*****************************************************************************
254 * Stress: perform various stress tests
255 *****************************************************************************/
256 static int Stress( vlc_object_t *p_this, char const *psz_cmd,
257 vlc_value_t oldval, vlc_value_t newval, void *p_data )
259 vlc_object_t **pp_objects;
265 if( *newval.psz_string )
267 i_level = atoi( newval.psz_string );
272 else if( i_level > 200 )
274 /* It becomes quite dangerous above 150 */
283 /* Allocate required data */
284 ppsz_name = malloc( MAXVAR * i_level * sizeof(char*) );
285 psz_blob = malloc( 20 * MAXVAR * i_level * sizeof(char) );
286 for( i = 0; i < MAXVAR * i_level; i++ )
288 ppsz_name[i] = psz_blob + 20 * i;
291 pp_objects = malloc( MAXOBJ * i_level * sizeof(void*) );
296 printf( "Test #1: objects\n" );
298 printf( " - creating %i objects\n", MAXOBJ * i_level );
300 for( i = 0; i < MAXOBJ * i_level; i++ )
302 pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC );
305 printf( " - randomly looking up %i objects\n", MAXLOOK * i_level );
306 for( i = MAXLOOK * i_level; i--; )
308 int id = (int) (MAXOBJ * i_level * 1.0 * rand() / (RAND_MAX));
309 vlc_object_get( p_this, pp_objects[id]->i_object_id );
312 printf( " - destroying the objects (LIFO)\n" );
313 for( i = MAXOBJ * i_level; i--; )
315 vlc_object_destroy( pp_objects[i] );
318 printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
321 * Test #2: integer variables
323 printf( "Test #2: integer variables\n" );
325 printf( " - creating %i integer variables\n", MAXVAR * i_level );
327 for( i = 0; i < MAXVAR * i_level; i++ )
329 sprintf( ppsz_name[i], "foo-%04i-bar-%04x", i, i * 11 );
330 var_Create( p_this, ppsz_name[i], VLC_VAR_INTEGER );
333 printf( " - randomly assigning %i values\n", MAXSET * i_level );
334 for( i = 0; i < MAXSET * i_level; i++ )
336 int v = (int) (MAXVAR * i_level * 1.0 * rand() / (RAND_MAX));
337 var_Set( p_this, ppsz_name[v], (vlc_value_t)i );
340 printf( " - destroying the variables\n" );
341 for( i = 0; i < MAXVAR * i_level; i++ )
343 var_Destroy( p_this, ppsz_name[i] );
346 printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
349 * Test #3: string variables
351 printf( "Test #3: string variables\n" );
353 printf( " - creating %i string variables\n", MAXVAR * i_level );
355 for( i = 0; i < MAXVAR * i_level; i++ )
357 sprintf( ppsz_name[i], "foo-%04i-bar-%04x", i, i * 11 );
358 var_Create( p_this, ppsz_name[i], VLC_VAR_STRING );
361 printf( " - randomly assigning %i values\n", MAXSET * i_level );
362 for( i = 0; i < MAXSET * i_level; i++ )
364 int v = (int) (MAXVAR * i_level * 1.0 * rand() / (RAND_MAX));
365 var_Set( p_this, ppsz_name[v], (vlc_value_t)ppsz_name[v] );
368 printf( " - destroying the variables\n" );
369 for( i = 0; i < MAXVAR * i_level; i++ )
371 var_Destroy( p_this, ppsz_name[i] );
374 printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
379 printf( "Test #4: threads\n" );
382 printf( " - spawning %i threads that will each create %i objects\n",
383 MAXTH * i_level, MAXOBJ/MAXTH );
384 for( i = 0; i < MAXTH * i_level; i++ )
386 pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC );
387 vlc_thread_create( pp_objects[i], "foo", Dummy, 0, VLC_TRUE );
390 printf( " - killing the threads (LIFO)\n" );
391 for( i = MAXTH * i_level; i--; )
393 pp_objects[i]->b_die = VLC_TRUE;
394 vlc_thread_join( pp_objects[i] );
395 vlc_object_destroy( pp_objects[i] );
398 printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
400 /* Free required data */
408 /*****************************************************************************
409 * Dummy: used by stress-test, creates objects and then do nothing.
410 *****************************************************************************/
411 static void * Dummy( vlc_object_t *p_this )
414 vlc_object_t *pp_objects[MAXOBJ/MAXTH];
416 for( i = 0; i < MAXOBJ/MAXTH; i++ )
418 pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC );
421 vlc_thread_ready( p_this );
423 while( !p_this->b_die )
428 for( i = MAXOBJ/MAXTH; i--; )
430 vlc_object_destroy( pp_objects[i] );
436 /*****************************************************************************
437 * Signal: send a signal to the current thread.
438 *****************************************************************************/
439 static int Signal( vlc_object_t *p_this, char const *psz_cmd,
440 vlc_value_t oldval, vlc_value_t newval, void *p_data )
442 raise( atoi(newval.psz_string) );