diff --git a/test/Makefile.am b/test/Makefile.am index 241981d0..60aac2b0 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,5 +1,6 @@ # don't run test_thumbnail.sh by default, it takes ages TESTS = \ + test_streams.sh \ test_descriptors.sh \ test_cli.sh \ test_formats.sh \ @@ -10,11 +11,15 @@ SUBDIRS = \ test-suite noinst_PROGRAMS = \ - test_descriptors + test_descriptors \ + test_streams test_descriptors_SOURCES = \ test_descriptors.c +test_streams_SOURCES = \ + test_streams.c + AM_CPPFLAGS = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@ AM_LDFLAGS = @LDFLAGS@ LDADD = @VIPS_CFLAGS@ ${top_builddir}/libvips/libvips.la @VIPS_LIBS@ @@ -22,6 +27,8 @@ LDADD = @VIPS_CFLAGS@ ${top_builddir}/libvips/libvips.la @VIPS_LIBS@ EXTRA_DIST = \ variables.sh.in \ test_cli.sh \ + test_descriptors.sh \ + test_streams.sh \ test_formats.sh \ test_seq.sh \ test_thumbnail.sh \ diff --git a/test/test_formats.sh b/test/test_formats.sh index 96992123..4d7b8319 100755 --- a/test/test_formats.sh +++ b/test/test_formats.sh @@ -51,30 +51,6 @@ save_load() { fi } -# is a difference beyond a threshold? return 0 (meaning all ok) or 1 (meaning -# error, or outside threshold) -break_threshold() { - diff=$1 - threshold=$2 - return $(echo "$diff <= $threshold" | bc -l) -} - -# subtract, look for max difference less than a threshold -test_difference() { - before=$1 - after=$2 - threshold=$3 - - $vips subtract $before $after $tmp/difference.v - $vips abs $tmp/difference.v $tmp/abs.v - dif=$($vips max $tmp/abs.v) - - if break_threshold $dif $threshold; then - echo "save / load difference is $dif" - exit 1 - fi -} - # save to the named file in tmp, convert back to vips again, subtract, look # for max difference less than a threshold test_format() { diff --git a/test/test_streams b/test/test_streams new file mode 100755 index 00000000..b7e8f017 --- /dev/null +++ b/test/test_streams @@ -0,0 +1,210 @@ +#! /bin/bash + +# test_streams - temporary wrapper script for .libs/test_streams +# Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-11 +# +# The test_streams program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.4.6' + notinst_deplibs=' ../libvips/libvips.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + file="$0" + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + ECHO="printf %s\\n" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string --lt- +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's ../libtool value, followed by no. +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=$0 + shift + for lt_opt + do + case "$lt_opt" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` + test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. + lt_dump_F=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%^.*/%%'` + cat "$lt_dump_D/$lt_dump_F" + exit 0 + ;; + --lt-*) + $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n "$lt_option_debug"; then + echo "test_streams:test_streams:$LINENO: libtool wrapper (GNU libtool) 2.4.6 Debian-2.4.6-11" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + $ECHO "test_streams:test_streams:$LINENO: newargv[$lt_dump_args_N]: $lt_arg" + lt_dump_args_N=`expr $lt_dump_args_N + 1` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ + + if test -n "$lt_option_debug"; then + $ECHO "test_streams:test_streams:$LINENO: newargv[0]: $progdir/$program" 1>&2 + func_lt_dump_args ${1+"$@"} 1>&2 + fi + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from $@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case " $* " in + *\ --lt-*) + for lt_wr_arg + do + case $lt_wr_arg in + --lt-*) ;; + *) set x "$@" "$lt_wr_arg"; shift;; + esac + shift + done ;; + esac + func_exec_program_core ${1+"$@"} +} + + # Parse options + func_parse_lt_options "$0" ${1+"$@"} + + # Find the directory that this script lives in. + thisdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "$file" | /bin/sed 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program='test_streams' + progdir="$thisdir/.libs" + + + if test -f "$progdir/$program"; then + # Add our own library path to LD_LIBRARY_PATH + LD_LIBRARY_PATH="/home/john/GIT/libvips/libvips/.libs:/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH" + + # Some systems cannot cope with colon-terminated LD_LIBRARY_PATH + # The second colon is a workaround for a bug in BeOS R4 sed + LD_LIBRARY_PATH=`$ECHO "$LD_LIBRARY_PATH" | /bin/sed 's/::*$//'` + + export LD_LIBRARY_PATH + + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + func_exec_program ${1+"$@"} + fi + else + # The program doesn't exist. + $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + $ECHO "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/test/test_streams.c b/test/test_streams.c new file mode 100644 index 00000000..4c48bc94 --- /dev/null +++ b/test/test_streams.c @@ -0,0 +1,151 @@ +/* Test stream*u. + */ + +#include +#include +#include +#include +#include + +typedef struct _MyInput { + const char *filename; + const unsigned char *contents; + size_t length; + size_t read_position; +} MyInput; + +typedef struct _MyOutput { + const char *filename; + int fd; +} MyOutput; + +static gint64 +read_cb( VipsStreamiu *streamiu, + void *buffer, gint64 length, MyInput *my_input ) +{ + gint64 bytes_read = VIPS_MIN( length, + my_input->length - my_input->read_position ); + + /* + printf( "read_cb: buffer = 0x%p, length = %zd\n", buffer, length ); + */ + + memcpy( buffer, + my_input->contents + my_input->read_position, bytes_read ); + my_input->read_position += bytes_read; + + return( bytes_read ); +} + +static gint64 +seek_cb( VipsStreamiu *streamiu, + gint64 offset, int whence, MyInput *my_input ) +{ + gint64 new_pos; + + /* + printf( "seek_cb: offset = %zd, whence = %d\n", offset, whence ); + */ + + switch( whence ) { + case SEEK_SET: + new_pos = offset; + break; + + case SEEK_CUR: + new_pos = my_input->read_position + offset; + break; + + case SEEK_END: + new_pos = my_input->length + offset; + break; + + default: + vips_error( "demo", "%s", "bad 'whence'" ); + return( -1 ); + } + + my_input->read_position = VIPS_CLIP( 0, new_pos, my_input->length ); + + return( my_input->read_position ); +} + +static gint64 +write_cb( VipsStreamou *streamou, + const void *data, gint64 length, MyOutput *my_output ) +{ + gint64 bytes_written; + + /* + printf( "write_cb: data = 0x%p, length = %zd\n", data, length ); + */ + + bytes_written = write( my_output->fd, data, length ); + + return( bytes_written ); +} + +static void +finish_cb( VipsStreamou *streamou, MyOutput *my_output ) +{ + /* + printf( "finish_cb:\n" ); + */ + + close( my_output->fd ); + my_output->fd = -1; +} + +int +main( int argc, char **argv ) +{ + MyInput my_input; + MyOutput my_output; + VipsStreamiu *streamiu; + VipsStreamou *streamou; + VipsImage *image; + + if( VIPS_INIT( NULL ) ) + return( -1 ); + + my_input.filename = argv[1]; + my_input.contents = NULL; + my_input.length = 0; + my_input.read_position = 0; + + if( !g_file_get_contents( my_input.filename, + (char **) &my_input.contents, &my_input.length, NULL ) ) + vips_error_exit( "unable to load from %s", my_input.filename ); + + streamiu = vips_streamiu_new(); + g_signal_connect( streamiu, "seek", G_CALLBACK( seek_cb ), &my_input ); + g_signal_connect( streamiu, "read", G_CALLBACK( read_cb ), &my_input ); + + if( !(image = vips_image_new_from_stream( VIPS_STREAMI( streamiu ), "", + "access", VIPS_ACCESS_SEQUENTIAL, + NULL )) ) + vips_error_exit( NULL ); + + my_output.filename = argv[2]; + my_output.fd = -1; + + if( (my_output.fd = vips__open( my_output.filename, + O_WRONLY | O_CREAT | O_TRUNC, 0644 )) == -1 ) + vips_error_exit( "unable to save to %s", my_output.filename ); + + streamou = vips_streamou_new(); + g_signal_connect( streamou, "write", + G_CALLBACK( write_cb ), &my_output ); + g_signal_connect( streamou, "finish", + G_CALLBACK( finish_cb ), &my_output ); + + if( vips_image_write_to_stream( image, ".png", + VIPS_STREAMO( streamou ), NULL ) ) + vips_error_exit( NULL ); + + VIPS_UNREF( image ); + VIPS_UNREF( streamiu ); + VIPS_UNREF( streamou ); + + return( 0 ); +} diff --git a/test/test_streams.sh b/test/test_streams.sh new file mode 100755 index 00000000..c0a578e5 --- /dev/null +++ b/test/test_streams.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +# test load and save via stream*u + +# set -x +set -e + +. ./variables.sh + +if test_supported jpegload_stream; then + ./test_streams $image $tmp/x.png + + # test max difference < 10 + test_difference $image $tmp/x.png 10 +fi diff --git a/test/variables.sh.in b/test/variables.sh.in index 0e4c3136..a949c74a 100644 --- a/test/variables.sh.in +++ b/test/variables.sh.in @@ -25,3 +25,27 @@ test_supported() { return $result } + +# is a difference beyond a threshold? return 0 (meaning all ok) or 1 (meaning +# error, or outside threshold) +break_threshold() { + diff=$1 + threshold=$2 + return $(echo "$diff <= $threshold" | bc -l) +} + +# subtract, look for max difference less than a threshold +test_difference() { + before=$1 + after=$2 + threshold=$3 + + $vips subtract $before $after $tmp/difference.v + $vips abs $tmp/difference.v $tmp/abs.v + dif=$($vips max $tmp/abs.v) + + if break_threshold $dif $threshold; then + echo "save / load difference is $dif" + exit 1 + fi +}