[vlc-devel] [RFC PATCH 2/3] test: add input/stream

Thomas Guillem thomas at gllm.fr
Wed Oct 21 12:11:42 CEST 2015


new version without md5 and with more more test:

- Read the whole file
- Test cache skip (read offset +1)
- Test seek and peek

If TEST_HTTP is defined, this will test a http url with cache_read and
prefetch.

TEST_HTTP is not defined by default because this test may last more than
10 seconds.

On Wed, Oct 21, 2015, at 12:09, Thomas Guillem wrote:
> This test compare IO output/returns between libc FILE functions and
> stream
> functions, with and without a stream-filter cache.
> ---
>  test/Makefile.am        |   3 +
>  test/src/input/stream.c | 366
>  ++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 369 insertions(+)
>  create mode 100644 test/src/input/stream.c
> 
> diff --git a/test/Makefile.am b/test/Makefile.am
> index ae1f492..c83bea9 100644
> --- a/test/Makefile.am
> +++ b/test/Makefile.am
> @@ -21,6 +21,7 @@ check_PROGRAMS = \
>  	test_src_config_chain \
>  	test_src_misc_variables \
>  	test_src_crypto_update \
> +       test_src_input_stream \
>          $(NULL)
>  
>  check_SCRIPTS = \
> @@ -79,6 +80,8 @@ test_src_config_chain_SOURCES = src/config/chain.c
>  test_src_config_chain_LDADD = $(LIBVLCCORE)
>  test_src_crypto_update_SOURCES = src/crypto/update.c
>  test_src_crypto_update_LDADD = $(LIBVLCCORE) $(GCRYPT_LIBS)
> +test_src_input_stream_SOURCES = src/input/stream.c
> +test_src_input_stream_LDADD = $(LIBVLCCORE) $(LIBVLC)
>  
>  checkall:
>  	$(MAKE) check_PROGRAMS="$(check_PROGRAMS) $(EXTRA_PROGRAMS)" check
> diff --git a/test/src/input/stream.c b/test/src/input/stream.c
> new file mode 100644
> index 0000000..3951c74
> --- /dev/null
> +++ b/test/src/input/stream.c
> @@ -0,0 +1,366 @@
> +/*****************************************************************************
> + * stream.c test streams and stream filters
> +
> *****************************************************************************
> + * Copyright (C) 2015 VLC authors and VideoLAN
> + *
> + * This program is free software; you can redistribute it and/or modify
> it
> + * under the terms of the GNU Lesser General Public License as published
> by
> + * the Free Software Foundation; either version 2.1 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
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> License
> + * along with this program; if not, write to the Free Software
> Foundation,
> + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
> +
> *****************************************************************************/
> +
> +#include "../../libvlc/test.h"
> +#include "../lib/libvlc_internal.h"
> +
> +#include <vlc_md5.h>
> +#include <vlc_stream.h>
> +
> +#include <limits.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <unistd.h>
> +
> +
> +// #define TEST_HTTP
> +#define HTTP_URL "http://streams.videolan.org/streams/ogm/MJPEG.ogm"
> +
> +struct reader
> +{
> +    char *psz_name;
> +    union {
> +        FILE *f;
> +        stream_t *s;
> +    } u;
> +    void *p_data;
> +
> +    void        (*pf_close)( struct reader * );
> +    uint64_t    (*pf_getsize)( struct reader * );
> +    ssize_t     (*pf_read)( struct reader *, void *, size_t );
> +    ssize_t     (*pf_peek)( struct reader *, const uint8_t **, size_t );
> +    uint64_t    (*pf_tell)( struct reader * );
> +    int         (*pf_seek)( struct reader *, uint64_t );
> +};
> +
> +static uint64_t
> +libc_getsize( struct reader *p_reader )
> +{
> +    struct stat st;
> +    int i_fd = fileno( p_reader->u.f );
> +
> +    assert( i_fd >= 0 );
> +    assert( fstat( i_fd, &st ) != -1 );
> +
> +    return st.st_size;
> +}
> +
> +static ssize_t
> +libc_read( struct reader *p_reader, void *p_buf, size_t i_len )
> +{
> +    return fread( p_buf, 1, i_len , p_reader->u.f );
> +}
> +
> +static ssize_t
> +libc_peek( struct reader *p_reader, const uint8_t **pp_buf, size_t i_len
> )
> +{
> +    ssize_t i_ret;
> +    long i_last_pos;
> +
> +    free( p_reader->p_data );
> +    p_reader->p_data = malloc( i_len );
> +    assert( p_reader->p_data );
> +
> +    i_last_pos = ftell( p_reader->u.f );
> +
> +    i_ret = fread( p_reader->p_data, 1, i_len, p_reader->u.f );
> +    *pp_buf = p_reader->p_data;
> +
> +    assert( fseek( p_reader->u.f, i_last_pos, SEEK_SET ) == 0 );
> +    return i_ret;
> +}
> +
> +static uint64_t
> +libc_tell( struct reader *p_reader )
> +{
> +    long i_ret = ftell( p_reader->u.f );
> +    assert( i_ret >= 0 );
> +    return i_ret;
> +}
> +
> +static int
> +libc_seek( struct reader *p_reader, uint64_t i_offset )
> +{
> +    return fseek( p_reader->u.f, (long) i_offset, SEEK_SET );
> +}
> +
> +static void
> +libc_close( struct reader *p_reader )
> +{
> +    fclose( p_reader->u.f );
> +    free( p_reader->p_data );
> +    free( p_reader->psz_name );
> +    free( p_reader );
> +}
> +
> +static struct reader *
> +libc_open( const char *psz_file )
> +{
> +    struct reader *p_reader = calloc( 1, sizeof(struct reader) );
> +    assert( p_reader );
> +
> +    p_reader->u.f = fopen( psz_file, "r" );
> +    if( !p_reader->u.f )
> +    {
> +        free( p_reader );
> +        return NULL;
> +    }
> +    p_reader->pf_close = libc_close;
> +    p_reader->pf_getsize = libc_getsize;
> +    p_reader->pf_read = libc_read;
> +    p_reader->pf_peek = libc_peek;
> +    p_reader->pf_tell = libc_tell;
> +    p_reader->pf_seek = libc_seek;
> +    p_reader->psz_name = strdup( "libc" );
> +    assert( p_reader->psz_name );
> +    return p_reader;
> +}
> +
> +static uint64_t
> +stream_getsize( struct reader *p_reader )
> +{
> +    uint64_t i_size;
> +
> +    assert( stream_GetSize( p_reader->u.s, &i_size ) == 0 );
> +    return i_size;
> +}
> +
> +static ssize_t
> +stream_read( struct reader *p_reader, void *p_buf, size_t i_len )
> +{
> +    return stream_Read( p_reader->u.s, p_buf, i_len );
> +}
> +
> +static ssize_t
> +stream_peek( struct reader *p_reader, const uint8_t **pp_buf, size_t
> i_len )
> +{
> +    return stream_Peek( p_reader->u.s, pp_buf, i_len );
> +}
> +
> +static uint64_t
> +stream_tell( struct reader *p_reader )
> +{
> +    return stream_Tell( p_reader->u.s );
> +}
> +
> +static int
> +stream_seek( struct reader *p_reader, uint64_t i_offset )
> +{
> +    return stream_Seek( p_reader->u.s, i_offset );
> +}
> +
> +static void
> +stream_close( struct reader *p_reader )
> +{
> +    stream_Delete( p_reader->u.s );
> +    libvlc_release( p_reader->p_data );
> +    free( p_reader->psz_name );
> +    free( p_reader );
> +}
> +
> +static struct reader *
> +stream_open( const char *psz_url, const char *psz_cachename )
> +{
> +    libvlc_instance_t *p_vlc;
> +    struct reader *p_reader;
> +    const char * args[] = {
> +        "-vvv",
> +        "--ignore-config",
> +        "-I",
> +        "dummy",
> +        "--no-media-library",
> +        "--vout=dummy",
> +        "--aout=dummy",
> +        "--stream-cache", psz_cachename,
> +    };
> +
> +    p_reader = calloc( 1, sizeof(struct reader) );
> +    assert( p_reader );
> +
> +    p_vlc = libvlc_new( sizeof(args) / sizeof(args[0]), args );
> +    assert( p_vlc != NULL );
> +
> +    p_reader->u.s = stream_UrlNew( p_vlc->p_libvlc_int, psz_url );
> +    if( !p_reader->u.s )
> +    {
> +        libvlc_release( p_vlc );
> +        free( p_reader );
> +        return NULL;
> +    }
> +    p_reader->pf_close = stream_close;
> +    p_reader->pf_getsize = stream_getsize;
> +    p_reader->pf_read = stream_read;
> +    p_reader->pf_peek = stream_peek;
> +    p_reader->pf_tell = stream_tell;
> +    p_reader->pf_seek = stream_seek;
> +    p_reader->p_data = p_vlc;
> +    assert( asprintf( &p_reader->psz_name, "stream with %s",
> psz_cachename ) >= 0 );
> +    return p_reader;
> +}
> +
> +static ssize_t
> +read_at( struct reader **pp_readers, unsigned int i_readers,
> +         void *p_buf, uint64_t i_offset,
> +         size_t i_read, uint64_t i_size )
> +{
> +    void *p_cmp_buf = NULL;
> +    ssize_t i_cmp_ret = 0;
> +    log( "%s %zu @ %lu\n", p_buf ? "read" : "peek", i_read, i_offset );
> +
> +    for( unsigned i = 0; i < i_readers; ++i )
> +    {
> +        ssize_t i_ret;
> +        uint64_t i_last_pos;
> +        const uint8_t *p_peek = NULL;
> +        struct reader *p_reader = pp_readers[i];
> +
> +        assert( p_reader->pf_seek( p_reader, i_offset ) != -1 );
> +
> +        i_last_pos = p_reader->pf_tell( p_reader );
> +        assert( i_last_pos == i_offset );
> +
> +        if( p_buf )
> +        {
> +            i_ret = p_reader->pf_read( p_reader, p_buf, i_read );
> +            assert( i_ret >= 0 );
> +            assert( p_reader->pf_tell( p_reader ) == i_ret + i_last_pos
> );
> +        }
> +        else
> +        {
> +            i_ret = p_reader->pf_peek( p_reader, &p_peek, i_read );
> +            assert( i_ret >= 0 );
> +            assert( p_reader->pf_tell( p_reader ) == i_last_pos );
> +            if( i_ret > 0 )
> +                assert( p_peek );
> +        }
> +
> +        if( i_offset < i_size )
> +            assert( (size_t) i_ret == __MIN( i_read, i_size - i_last_pos
> ) );
> +
> +        if( i == 0 )
> +        {
> +            if( i_ret > 0 )
> +            {
> +                p_cmp_buf = malloc( i_ret );
> +                assert( p_cmp_buf );
> +                memcpy( p_cmp_buf, p_buf ? p_buf : p_peek, i_ret );
> +            }
> +            i_cmp_ret = i_ret;
> +        }
> +        else
> +        {
> +            assert( i_cmp_ret == i_ret );
> +            if( i_ret > 0 )
> +                assert( memcmp( p_cmp_buf, p_buf ? p_buf : p_peek, i_ret
> ) == 0 );
> +        }
> +    }
> +    free( p_cmp_buf );
> +    return i_cmp_ret;
> +}
> +
> +static void
> +test( struct reader **pp_readers, unsigned int i_readers )
> +{
> +#define READ_AT( i_offset, i_read ) \
> +    read_at( pp_readers, i_readers, p_buf, i_offset, i_read, i_size )
> +#define PEEK_AT( i_offset, i_read ) \
> +    read_at( pp_readers, i_readers, NULL, i_offset, i_read, i_size )
> +    uint8_t p_buf[4096];
> +    ssize_t i_ret = 0;
> +    uint64_t i_offset = 0;
> +    uint64_t i_size;
> +
> +    /* Compare size between each readers */
> +    i_size = pp_readers[0]->pf_getsize( pp_readers[0] );
> +    log( "stream size: %lu\n", i_size );
> +    for( unsigned int i = 1; i < i_readers; ++i )
> +        assert( pp_readers[i]->pf_getsize( pp_readers[i] ) == i_size );
> +
> +    /* Read the whole file and compare between each readers */
> +    while( ( i_ret = READ_AT( i_offset, 4096 ) ) > 0 )
> +        i_offset += i_ret;
> +
> +    /* Test cache skip */
> +    i_offset = 9 * i_size / 10;
> +    while( ( i_ret = READ_AT( i_offset, 4096 ) ) > 0 )
> +        i_offset += i_ret + 1;
> +
> +    /* Test seek and peek */
> +    READ_AT( 0, 42 );
> +    READ_AT( i_size - 5, 43 );
> +    READ_AT( i_size, 43 );
> +    READ_AT( i_size + 1, 43 );
> +    READ_AT( i_size * 2, 43 );
> +    READ_AT( 99999999LL, 44 );
> +    READ_AT( 1, 45 );
> +    READ_AT( 2, 45 );
> +    READ_AT( i_size / 2, 45 );
> +    READ_AT( 2, 45 );
> +    READ_AT( 1, 45 );
> +    PEEK_AT( 0, 46 );
> +    PEEK_AT( i_size - 23, 46 );
> +    PEEK_AT( i_size, 46 );
> +    PEEK_AT( i_size / 2, 46 );
> +    PEEK_AT( i_size * 2, 46 );
> +    PEEK_AT( 0, 46 );
> +}
> +
> +int
> +main( void )
> +{
> +    char psz_file[PATH_MAX];
> +    char *psz_url;
> +    struct reader *pp_readers[3];
> +
> +    test_init();
> +
> +    log( "Test local file with libc, stream, and stream with
> cache_read\n" );
> +    assert( realpath( SRCDIR"/samples/image.jpg", psz_file ) == psz_file
> );
> +    assert( asprintf( &psz_url, "file://%s", psz_file ) != -1 );
> +
> +    assert( ( pp_readers[0] = libc_open( psz_file ) ) );
> +    assert( ( pp_readers[1] = stream_open( psz_url, "none" ) ) );
> +    assert( ( pp_readers[2] = stream_open( psz_url, "cache_read" ) ) );
> +
> +    test( pp_readers, 3 );
> +    for( unsigned int i = 0; i < 3; ++i )
> +        pp_readers[i]->pf_close( pp_readers[i] );
> +    free( psz_url );
> +
> +#ifdef TEST_HTTP
> +    log( "Test http url with stream, stream with cache_read "
> +         "and stream with prefetch\n" );
> +    alarm( 0 );
> +    if( !( pp_readers[0] = stream_open( HTTP_URL, "none" ) ) )
> +    {
> +        log( "WARNING: can't test http url" );
> +        return 0;
> +    }
> +    assert( ( pp_readers[1] = stream_open( HTTP_URL, "cache_read" ) ) );
> +    assert( ( pp_readers[2] = stream_open( HTTP_URL, "prefetch" ) ) );
> +
> +    test( pp_readers, 3 );
> +    for( unsigned int i = 0; i < 3; ++i )
> +        pp_readers[i]->pf_close( pp_readers[i] );
> +#endif
> +
> +    assert( false );
> +    return 0;
> +}
> -- 
> 2.1.4
> 


More information about the vlc-devel mailing list