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

Thomas Guillem thomas at gllm.fr
Wed Oct 21 12:09:08 CEST 2015


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