/*****************************************************************************
* test4.c : Miscellaneous stress tests module for vlc
*****************************************************************************
- * Copyright (C) 2002 VideoLAN
- * $Id: test4.c,v 1.1 2002/10/14 16:34:17 sam Exp $
+ * Copyright (C) 2002 the VideoLAN team
+ * $Id$
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
-#include <vlc/vlc.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
-#include <stdlib.h>
#include <signal.h>
/*****************************************************************************
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
-static int Stress ( vlc_object_t *, char *, char * );
+static int Foo ( vlc_object_t *, char const *,
+ vlc_value_t, vlc_value_t, void * );
+static int Callback ( vlc_object_t *, char const *,
+ vlc_value_t, vlc_value_t, void * );
+static int MyCallback( vlc_object_t *, char const *,
+ vlc_value_t, vlc_value_t, void * );
+static void * MyThread ( vlc_object_t * );
+
+static int Stress ( vlc_object_t *, char const *,
+ vlc_value_t, vlc_value_t, void * );
static void * Dummy ( vlc_object_t * );
-static int Signal ( vlc_object_t *, char *, char * );
+static int Signal ( vlc_object_t *, char const *,
+ vlc_value_t, vlc_value_t, void * );
/*****************************************************************************
* Module descriptor.
*****************************************************************************/
-vlc_module_begin();
- set_description( _("Miscellaneous stress tests") );
- var_Create( p_module->p_libvlc, "stress", VLC_VAR_COMMAND );
- var_Set( p_module->p_libvlc, "stress", (vlc_value_t)(void*)Stress );
- var_Create( p_module->p_libvlc, "signal", VLC_VAR_COMMAND );
- var_Set( p_module->p_libvlc, "signal", (vlc_value_t)(void*)Signal );
-vlc_module_end();
+vlc_module_begin ()
+ set_description( N_("Miscellaneous stress tests") )
+ var_Create( p_module->p_libvlc, "foo-test",
+ VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
+ var_AddCallback( p_module->p_libvlc, "foo-test", Foo, NULL );
+ var_Create( p_module->p_libvlc, "callback-test",
+ VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
+ var_AddCallback( p_module->p_libvlc, "callback-test", Callback, NULL );
+ var_Create( p_module->p_libvlc, "stress-test",
+ VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
+ var_AddCallback( p_module->p_libvlc, "stress-test", Stress, NULL );
+ var_Create( p_module->p_libvlc, "signal",
+ VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
+ var_AddCallback( p_module->p_libvlc, "signal", Signal, NULL );
+vlc_module_end ()
+
+/*****************************************************************************
+ * Foo: put anything here
+ *****************************************************************************/
+static int Foo( vlc_object_t *p_this, char const *psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+ vlc_value_t val;
+ int i;
+
+ var_Create( p_this, "honk", VLC_VAR_STRING | VLC_VAR_HASCHOICE );
+
+ val.psz_string = "foo";
+ var_Change( p_this, "honk", VLC_VAR_ADDCHOICE, &val, NULL );
+ val.psz_string = "bar";
+ var_Change( p_this, "honk", VLC_VAR_ADDCHOICE, &val, NULL );
+ val.psz_string = "baz";
+ var_Change( p_this, "honk", VLC_VAR_ADDCHOICE, &val, NULL );
+ var_Change( p_this, "honk", VLC_VAR_SETDEFAULT, &val, NULL );
+
+ var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
+ free( val.psz_string );
+
+ val.psz_string = "foo";
+ var_Set( p_this, "honk", val );
+
+ var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
+ free( val.psz_string );
+
+ val.psz_string = "blork";
+ var_Set( p_this, "honk", val );
+
+ var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
+ free( val.psz_string );
+
+ val.psz_string = "baz";
+ var_Change( p_this, "honk", VLC_VAR_DELCHOICE, &val, NULL );
+
+ var_Get( p_this, "honk", &val ); printf( "value: %s\n", val.psz_string );
+
+ var_Change( p_this, "honk", VLC_VAR_GETLIST, &val, NULL );
+ for( i = 0 ; i < val.p_list->i_count ; i++ )
+ {
+ printf( "value %i: %s\n", i, val.p_list->p_values[i].psz_string );
+ }
+ var_FreeList( &val, NULL );
+
+ var_Destroy( p_this, "honk" );
+
+ return VLC_SUCCESS;
+}
/*****************************************************************************
- * Stress: perform various tests
+ * Callback: test callback functions
*****************************************************************************/
-static int Stress( vlc_object_t *p_this, char *psz_cmd, char *psz_arg )
+static int Callback( vlc_object_t *p_this, char const *psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+ int i;
+ char psz_var[20];
+ vlc_object_t *pp_objects[10];
+ vlc_value_t val;
+
+ /* Allocate a few variables */
+ for( i = 0; i < 1000; i++ )
+ {
+ sprintf( psz_var, "blork-%i", i );
+ var_Create( p_this, psz_var, VLC_VAR_INTEGER );
+ var_AddCallback( p_this, psz_var, MyCallback, NULL );
+ }
+
+ /*
+ * Test #1: callback loop detection
+ */
+ printf( "Test #1: callback loop detection\n" );
+
+ printf( " - without boundary check (vlc should print an error)\n" );
+ val.i_int = 1234567;
+ var_Set( p_this, "blork-12", val );
+
+ printf( " - with boundary check\n" );
+ val.i_int = 12;
+ var_Set( p_this, "blork-12", val );
+
+ /*
+ * Test #2: concurrent access
+ */
+ printf( "Test #2: concurrent access\n" );
+
+ printf( " - launch worker threads\n" );
+
+ for( i = 0; i < 10; i++ )
+ {
+ pp_objects[i] = vlc_object_create( p_this, sizeof( vlc_object_t ) );
+ vlc_object_attach( pp_objects[i], p_this );
+ vlc_thread_create( pp_objects[i], "foo", MyThread, 0, true );
+ }
+
+ msleep( 3000000 );
+
+ printf( " - kill worker threads\n" );
+
+ for( i = 0; i < 10; i++ )
+ {
+ vlc_object_kill( pp_objects[i] );
+ vlc_thread_join( pp_objects[i] );
+ vlc_object_release( pp_objects[i] );
+ }
+
+ /* Clean our mess */
+ for( i = 0; i < 1000; i++ )
+ {
+ sprintf( psz_var, "blork-%i", i );
+ var_DelCallback( p_this, psz_var, MyCallback, NULL );
+ var_Destroy( p_this, psz_var );
+ }
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * MyCallback: used by callback-test
+ *****************************************************************************/
+static int MyCallback( vlc_object_t *p_this, char const *psz_var,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+ int i_var = 1 + atoi( psz_var + strlen("blork-") );
+ char psz_newvar[20];
+
+ if( i_var == 1000 )
+ {
+ i_var = 0;
+ }
+
+ /* If we are requested to stop, then stop. */
+ if( i_var == newval.i_int )
+ {
+ return VLC_SUCCESS;
+ }
+
+ /* If we're the blork-3 callback, set blork-4, and so on. */
+ sprintf( psz_newvar, "blork-%i", i_var );
+ var_Set( p_this, psz_newvar, newval );
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * MyThread: used by callback-test, creates objects and then do nothing.
+ *****************************************************************************/
+static void * MyThread( vlc_object_t *p_this )
+{
+ char psz_var[20];
+ vlc_value_t val;
+ vlc_object_t *p_parent = p_this->p_parent;
+
+ vlc_thread_ready( p_this );
+
+ val.i_int = 42;
+
+ while( vlc_object_alive (p_this) )
+ {
+ int i = (int) (100.0 * rand() / (RAND_MAX));
+ /* FIXME: not thread-safe */
+
+ sprintf( psz_var, "blork-%i", i );
+ val.i_int = i + 200;
+ int canc = vlc_savecancel ();
+ var_Set( p_parent, psz_var, val );
+ vlc_restorecancel (canc);
+
+ /* This is quite heavy, but we only have 10 threads. Keep cool. */
+ msleep( 1000 );
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************
+ * Stress: perform various stress tests
+ *****************************************************************************/
+static int Stress( vlc_object_t *p_this, char const *psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
vlc_object_t **pp_objects;
mtime_t start;
char * psz_blob;
int i, i_level;
- if( *psz_arg )
+ if( *newval.psz_string )
{
- i_level = atoi( psz_arg );
+ i_level = atoi( newval.psz_string );
if( i_level <= 0 )
{
i_level = 1;
/* Allocate required data */
ppsz_name = malloc( MAXVAR * i_level * sizeof(char*) );
- psz_blob = malloc( 20 * MAXVAR * i_level * sizeof(char) );
+ psz_blob = malloc( 20 * MAXVAR * i_level );
for( i = 0; i < MAXVAR * i_level; i++ )
{
ppsz_name[i] = psz_blob + 20 * i;
start = mdate();
for( i = 0; i < MAXOBJ * i_level; i++ )
{
- pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC );
+ pp_objects[i] = vlc_object_create( p_this, sizeof( vlc_object_t ) );
}
printf( " - randomly looking up %i objects\n", MAXLOOK * i_level );
for( i = MAXLOOK * i_level; i--; )
{
int id = (int) (MAXOBJ * i_level * 1.0 * rand() / (RAND_MAX));
- vlc_object_get( p_this, pp_objects[id]->i_object_id );
+ vlc_object_get( pp_objects[id]->i_object_id );
+ vlc_object_release( p_this );
}
printf( " - destroying the objects (LIFO)\n" );
for( i = MAXOBJ * i_level; i--; )
{
- vlc_object_destroy( pp_objects[i] );
+ vlc_object_release( pp_objects[i] );
}
printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
MAXTH * i_level, MAXOBJ/MAXTH );
for( i = 0; i < MAXTH * i_level; i++ )
{
- pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC );
- vlc_thread_create( pp_objects[i], "foo", Dummy, 0, VLC_TRUE );
+ pp_objects[i] = vlc_object_create( p_this, sizeof( vlc_object_t ) );
+ vlc_thread_create( pp_objects[i], "foo", Dummy, 0, true );
}
printf( " - killing the threads (LIFO)\n" );
for( i = MAXTH * i_level; i--; )
{
- pp_objects[i]->b_die = VLC_TRUE;
+ pp_objects[i]->b_die = true;
vlc_thread_join( pp_objects[i] );
- vlc_object_destroy( pp_objects[i] );
+ vlc_object_release( pp_objects[i] );
}
printf( "done (%fs).\n", (mdate() - start) / 1000000.0 );
}
/*****************************************************************************
- * Dummy: used by test, creates objects and then do nothing.
+ * Dummy: used by stress-test, creates objects and then do nothing.
*****************************************************************************/
static void * Dummy( vlc_object_t *p_this )
{
for( i = 0; i < MAXOBJ/MAXTH; i++ )
{
- pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC );
+ pp_objects[i] = vlc_object_create( p_this, sizeof( vlc_object_t ) );
}
vlc_thread_ready( p_this );
- while( !p_this->b_die )
+ while( vlc_object_alive (p_this) )
{
- msleep( 1000 );
+ msleep( 10000 );
}
for( i = MAXOBJ/MAXTH; i--; )
{
- vlc_object_destroy( pp_objects[i] );
+ vlc_object_release( pp_objects[i] );
}
return NULL;
/*****************************************************************************
* Signal: send a signal to the current thread.
*****************************************************************************/
-static int Signal( vlc_object_t *p_this, char *psz_cmd, char *psz_arg )
+static int Signal( vlc_object_t *p_this, char const *psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
- raise( atoi(psz_arg) );
+ raise( atoi(newval.psz_string) );
return VLC_SUCCESS;
}
-