merged cehteh's work for the testsuite, automake and plugins

This commit is contained in:
Fischlurch 2007-08-17 05:52:48 +02:00
commit 5bde4020cf
21 changed files with 599 additions and 103 deletions

14
.gitignore vendored
View file

@ -1,11 +1,13 @@
/wiki/backups/*
/tests/*
*~
*.tar.*
.sconf_temp
.sconf_temp/*
.sconsign.dblite
.[^.]*
Buildhelper.pyc
optcache
.[^.]*
Makefile.in
build/*
autom4te.cache/*
scripts/*
configure
aclocal.m4
semantic.cache

46
Makefile.am Normal file
View file

@ -0,0 +1,46 @@
# Copyright (C) CinelerraCV
# 2007, Christian Thaeter <ct@pipapo.org>
#
# This program is free software; you can redistribute it and/or
# modify 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
# GNU General Public License for more details.
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
bin_PROGRAMS =
lib_LTLIBRARIES =
noinst_PROGRAMS =
check_PROGRAMS =
noinst_LIBRARIES =
noinst_LTLIBRARIES =
noinst_HEADERS =
BUILT_SOURCES =
EXTRA_DIST =
SUBDIRS =
# Only use subdirs if really needed, prefer the include scheme below
#SUBDIRS +=
# core
include $(top_srcdir)/src/lib/Makefile.am
# plugins
#include $(top_srcdir)/src...
# tests
include $(top_srcdir)/tests/Makefile.am
include $(top_srcdir)/tests/examples/Makefile.am
#EXTRA_DIST += admin debian doc depcomp README.BUILD LICENSE \
# cinelerra-cvs-current.spec
AUTOMAKE_OPTIONS=foreign
#ACLOCAL_AMFLAGS = -I m4

View file

@ -7,6 +7,8 @@
# see wiki/index.html#GitNotes%20GitAliases for information
git tag -s -f -m "signature generated by $(git config user.email)" "$(git config user.email)/$(git-symbolic-ref HEAD | cut -d/ -f 3-)_signature"
user_email="$(git config user.email)"
git tag -s -f -m "signature generated by $user_email" "$user_email/$(git-symbolic-ref HEAD | cut -d/ -f 3-)_signature"
git push --all public
git push public "refs/tags/$(git config user.email)/*"
git push public "refs/tags/$user_email/*"

73
configure.ac Normal file
View file

@ -0,0 +1,73 @@
AC_INIT(cinelerra, 3.0pre)
AC_CONFIG_SRCDIR(src/lib/plugin.c)
AC_CONFIG_AUX_DIR(scripts)
AM_INIT_AUTOMAKE
AC_PREREQ(2.59)
AC_COPYRIGHT([
Copyright (C) CinelerraCV
2007, Christian Thaeter <ct@pipapo.org>
This program is free software; you can redistribute it and/or
modify 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
GNU General Public License for more details.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
])
#
# Required programs
#
AC_PROG_CC
AC_PROG_CPP
AC_PROG_CXX
AC_PROG_LIBTOOL
#
# test for headers
#
AC_STDC_HEADERS
AC_CHECK_HEADER([pthread.h], AC_DEFINE(HAVE_PTHREAD_H))
AC_CHECK_HEADER([nobug.h], AC_DEFINE(HAVE_NOBUG_H))
AC_CHECK_HEADER([execinfo.h], AC_DEFINE(HAVE_EXECINFO_H))
# there is a warning in nobug, disabled til fixed AC_CHECK_HEADER([valgrind/valgrind.h], AC_DEFINE(HAVE_VALGRIND_VALGRIND_H))
#
# user options
#
############## NoBug build levels
AH_TEMPLATE(EBUG_ALPHA, [Define to 1 for selecting NoBug ALPHA build level])
AH_TEMPLATE(EBUG_BETA, [Define to 1 for selecting NoBug BETA build level])
AH_TEMPLATE(NDEBUG, [Define to 1 for selecting NoBug RELEASE build level])
AC_ARG_ENABLE(alpha, AC_HELP_STRING([--enable-alpha], [select NoBug ALPHA build level]),
nobug_level=alpha
AC_DEFINE(EBUG_ALPHA),
[
AC_ARG_ENABLE(beta, AC_HELP_STRING([--enable-beta], [select NoBug BETA build level]),
nobug_level=beta
AC_DEFINE(EBUG_BETA),
[
AC_ARG_ENABLE(release, AC_HELP_STRING([--enable-release], [select NoBug RELEASE build level]),
nobug_level=release
AC_DEFINE(NDEBUG),
# default to ALPHA
nobug_level=alpha
AC_DEFINE(EBUG_ALPHA)
)])])
AC_MSG_RESULT([NoBug build level: $nobug_level])
# END NoBug
AC_CONFIG_FILES(Makefile)
AC_OUTPUT

1
scripts/DIR_INFO Normal file
View file

@ -0,0 +1 @@
autotools helper scripts

24
src/lib/Makefile.am Normal file
View file

@ -0,0 +1,24 @@
# Copyright (C) CinelerraCV
# 2007, Christian Thaeter <ct@pipapo.org>
#
# This program is free software; you can redistribute it and/or
# modify 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
# GNU General Public License for more details.
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
libcin3_a_srcdir = $(top_srcdir)/src/lib
noinst_LIBRARIES += libcin3.a
libcin3_a_CFLAGS = $(CFLAGS) -std=gnu99 -Wall -Werror
libcin3_a_SOURCES = $(libcin3_a_srcdir)/plugin.c $(libcin3_a_srcdir)/error.c
noinst_HEADERS += $(libcin3_a_srcdir)/plugin.h $(libcin3_a_srcdir)/error.h

56
src/lib/error.c Normal file
View file

@ -0,0 +1,56 @@
/*
error.c - Cinelerra Error handling
Copyright (C) CinelerraCV
2007, Christian Thaeter <ct@pipapo.org>
This program is free software; you can redistribute it and/or
modify 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
GNU General Public License for more details.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <pthread.h>
/* Thread local storage */
static pthread_key_t cinelerra_error_tls;
static pthread_once_t cinelerra_error_initialized = PTHREAD_ONCE_INIT;
static void
cinelerra_error_tls_init (void)
{
pthread_key_create (&cinelerra_error_tls, NULL);
}
const char*
cinelerra_error_set (const char * nerr)
{
pthread_once (&cinelerra_error_initialized, cinelerra_error_tls_init);
const char* err = pthread_getspecific (cinelerra_error_tls);
if (!err)
pthread_setspecific (cinelerra_error_tls, nerr);
return err;
}
const char*
cinelerra_error ()
{
pthread_once (&cinelerra_error_initialized, cinelerra_error_tls_init);
const char* err = pthread_getspecific (cinelerra_error_tls);
if (err)
pthread_setspecific (cinelerra_error_tls, NULL);
return err;
}

42
src/lib/error.h Normal file
View file

@ -0,0 +1,42 @@
/*
error.h - Cinelerra Error handling
Copyright (C) CinelerraCV
2007, Christian Thaeter <ct@pipapo.org>
This program is free software; you can redistribute it and/or
modify 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
GNU General Public License for more details.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef CINELERRA_ERROR_H
#define CINELERRA_ERROR_H
#include <nobug.h>
#include <stdlib.h>
#define CINELERRA_DIE(message) do { NOBUG_ERROR(NOBUG_ON, message); abort(); } while(0)
#define CINELERRA_ERROR_DECLARE(err) \
extern const char* CINELERRA_ERROR_##err
#define CINELERRA_ERROR_DEFINE(err, msg) \
const char* CINELERRA_ERROR_##err = "CINELERRA_ERROR_" #err ":" msg
const char*
cinelerra_error_set (const char * err);
const char*
cinelerra_error ();
#endif /* CINELERRA_ERROR_H */

View file

@ -19,6 +19,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <unistd.h>
#include <search.h>
#include <string.h>
#include <dlfcn.h>
@ -33,7 +34,7 @@
TODO move CINELERRA_DIE elsewhere (cinlib.h?)
*/
#define CINELERRA_DIE do{NOBUG_ERROR(NOBUG_ON, LOG_EMERG, "aborting due fatal error"); abort();}while(0)
#define CINELERRA_DIE do{NOBUG_LOG(NOBUG_ON, LOG_EMERG, "aborting due fatal error"); abort();}while(0)
/* TODO should be set by the build system to the actual plugin path */
#define CINELERRA_PLUGIN_PATH "~/.cinelerra3/plugins:/usr/local/lib/cinelerra3/plugins"
@ -43,7 +44,7 @@ NOBUG_DEFINE_FLAG (cinelerra_plugin);
/* errors */
const char* CINELERRA_PLUGIN_SUCCESS = NULL;
const char* CINELERRA_PLUGIN_EDLOPEN = "Could not open plugin";
const char* CINELERRA_PLUGIN_EDHOOK = "Hook function failed";
const char* CINELERRA_PLUGIN_EHOOK = "Hook function failed";
const char* CINELERRA_PLUGIN_ENFOUND = "No such plugin";
const char* CINELERRA_PLUGIN_ENIFACE = "No such interface";
const char* CINELERRA_PLUGIN_EREVISION = "Interface revision too old";
@ -62,15 +63,15 @@ enum cinelerra_plugin_type
static const struct
{
const char* const ext;
enum cinelerra_plugin_type;
enum cinelerra_plugin_type type;
} cinelerra_plugin_extensions [] =
{
"plugin", CINELERRA_PLUGIN_DYNLIB,
"so", CINELERRA_PLUGIN_DYNLIB,
"tcc", CINELERRA_PLUGIN_CSOURCE,
"c", CINELERRA_PLUGIN_CSOURCE,
{"plugin", CINELERRA_PLUGIN_DYNLIB},
{"so", CINELERRA_PLUGIN_DYNLIB},
{"tcc", CINELERRA_PLUGIN_CSOURCE},
{"c", CINELERRA_PLUGIN_CSOURCE},
/* extend here */
NULL, CINELERRA_PLUGIN_NULL
{NULL, CINELERRA_PLUGIN_NULL}
};
@ -153,7 +154,7 @@ cinelerra_plugin_lookup (struct cinelerra_plugin* self, const char* path)
strcpy(tpath, path);
/*for each in path*/
for (char* tok = strtok(tpath, ":", &tmp); tok; tok = strtok(NULL, ":", &tmp))
for (char* tok = strtok_r (tpath, ":", &tmp); tok; tok = strtok_r (NULL, ":", &tmp))
{
/*for each extension*/
for (int i = 0; cinelerra_plugin_extensions[i].ext; ++i)
@ -181,7 +182,7 @@ cinelerra_plugin_lookup (struct cinelerra_plugin* self, const char* path)
struct cinelerra_interface*
cinelerra_interface_open (const char* name, const char* interface, size_t min_revision)
{
REQUIRE (min_revision > sizeof(cinelerra_interface), "try to use an empty interface eh?");
//REQUIRE (min_revision > sizeof(struct cinelerra_interface), "try to use an empty interface eh?");
REQUIRE (interface, "interface name must be given");
pthread_once (&cinelerra_plugin_initialized, cinelerra_plugin_tls_init);
@ -208,7 +209,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
{
/*lookup for $CINELERRA_PLUGIN_PATH*/
(*found)->name = strdup (name);
if (!(*found)->name) CINELERA_DIE;
if (!(*found)->name) CINELERRA_DIE;
if (!cinelerra_plugin_lookup (*found, getenv("CINELERRA_PLUGIN_PATH"))
#ifdef CINELERRA_PLUGIN_PATH
@ -225,15 +226,14 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
{
(*found)->name = NULL;
(*found)->pathname = NULL;
(*found)->ext = NULL;
}
(*found)->use_count = 0;
PLANNED("if .so like then dlopen; else if .c like tcc compile");
TODO("factor dlopen and dlsym out")
TODO("factor dlopen and dlsym out");
(*found)->handle = dlopen (pathname, RTLD_NOW|RTLD_LOCAL);
(*found)->handle = dlopen ((*found)->pathname, RTLD_NOW|RTLD_LOCAL);
if (!(*found)->handle)
{
ERROR (cinelerra_plugin, "dlopen failed: %s", dlerror());
@ -304,11 +304,13 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
}
void
cinelerra_interface_close (struct cinelerra_interface* self)
cinelerra_interface_close (void* ptr)
{
if(!self)
if(!ptr)
return;
struct cinelerra_interface* self = (struct cinelerra_interface*) ptr;
pthread_mutex_lock (&cinelerra_plugin_mutex);
struct cinelerra_plugin* plugin = self->plugin;

View file

@ -109,7 +109,7 @@ cinelerra_interface_open (const char* plugin, const char* name, size_t min_revis
* @param self interface to be closed
*/
void
cinelerra_interface_close (struct cinelerra_interface* self);
cinelerra_interface_close (void* self);
/**
* Tries to unload a plugin.

13
tests/00test.tests Normal file
View file

@ -0,0 +1,13 @@
TESTING "test system selftest" cat
TEST "test cat'ing stdin to stdout" <<END
in: foo: bar
out: foo: bar
return: 0
END
TEST "test stderr, cat'ing noonexistant file" ,nonexistent_file <<END
err: cat: ,nonexistent_file: No such file or directory
return: 1
END

View file

@ -0,0 +1,27 @@
TESTING "Error handling" ./errortest
TEST "no error" <<END
return: 0
END
TEST "set error" set <<END
return: 0
END
TEST "query no error" get_no <<END
out: (nil)
return: 0
END
TEST "query error" get <<END
out: CINELERRA_ERROR_TEST:test error
return: 0
END
TEST "error cleared" get2 <<END
out: CINELERRA_ERROR_TEST:test error
out: (nil)
return: 0
END

5
tests/99examples.tests Normal file
View file

@ -0,0 +1,5 @@
TESTING "test plugin example code" ./plugin_example
TEST "plugin example" <<END
END

27
tests/Makefile.am Normal file
View file

@ -0,0 +1,27 @@
# Copyright (C) CinelerraCV
# 2007, Christian Thaeter <ct@pipapo.org>
# Hermann Vosseler <Ichthyostega@web.de>
#
# This program is free software; you can redistribute it and/or
# modify 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
# GNU General Public License for more details.
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
tests_srcdir = $(top_srcdir)/tests
check_PROGRAMS += errortest
errortest_SOURCES = $(tests_srcdir)/errortest.c
errortest_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/lib/
errortest_LDADD = $(builddir)/libcin3.a -lnobugmt -lpthread -ldl
TESTS = $(tests_srcdir)/test.sh

65
tests/errortest.c Normal file
View file

@ -0,0 +1,65 @@
/*
errortest.c - test error handling
Copyright (C) CinelerraCV
2007, Christian Thaeter <ct@pipapo.org>
This program is free software; you can redistribute it and/or
modify 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
GNU General Public License for more details.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <error.h>
#include <stdio.h>
#include <string.h>
CINELERRA_ERROR_DEFINE(TEST, "test error");
int
main (int argc, char** argv)
{
if (argc == 1)
return 0;
if (!strcmp(argv[1], "set"))
{
cinelerra_error_set (CINELERRA_ERROR_TEST);
}
if (!strcmp(argv[1], "get_no"))
{
const char* err;
err = cinelerra_error ();
printf ("%p\n", err);
}
if (!strcmp(argv[1], "get"))
{
cinelerra_error_set (CINELERRA_ERROR_TEST);
const char* err;
err = cinelerra_error ();
printf ("%s\n", err);
}
if (!strcmp(argv[1], "get2"))
{
cinelerra_error_set (CINELERRA_ERROR_TEST);
const char* err;
err = cinelerra_error ();
printf ("%s\n", err);
err = cinelerra_error ();
printf ("%p\n", err);
}
return 0;
}

View file

@ -0,0 +1,30 @@
# Copyright (C) CinelerraCV
# 2007, Christian Thaeter <ct@pipapo.org>
#
# This program is free software; you can redistribute it and/or
# modify 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
# GNU General Public License for more details.
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
examples_srcdir = $(top_srcdir)/tests/examples
noinst_PROGRAMS += plugin_example
plugin_example_CFLAGS = $(CFLAGS) -std=gnu99 -Wall -Werror
plugin_example_CPPFLAGS = $(CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/lib/
plugin_example_LDADD = $(builddir)/libcin3.a -lnobugmt -lpthread -ldl
plugin_example_SOURCES = $(examples_srcdir)/plugin_main.c
noinst_HEADERS += $(examples_srcdir)/hello_interface.h
#noinst_LTLIBRARIES += example_plugin.la
#example_plugin_la_CPPFLAGS = $(CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/lib/
#example_plugin_la_SOURCES = $(examples_srcdir)/example_plugin.c

View file

@ -5,40 +5,41 @@
int myopen(void)
{
printf("opened\n");
return 0;
}
int myclose(void);
int myclose(void)
{
printf("closed\n");
return 0;
}
int hallo(void)
void hallo(void)
{
printf("Hallo Welt!\n");
}
int tschuess(const char* m)
void tschuess(const char* m)
{
printf("Tschues %s\n", m);
}
int hello(void);
void hello(void)
{
printf("Hello world!\n");
}
int bye(const char* m)
void bye(const char* m)
{
printf("bye %s\n", m);
}
CINELERRA_INTERFACE_IMPLEMENT(hello, 1, german, myopen, myclose,
CINELERRA_INTERFACE_FUNC(hello, hallo),
CINELERRA_INTERFACE_FUNC(goodbye, tschuess)
//CINELERRA_INTERFACE_FUNC(hello, hallo),
//CINELERRA_INTERFACE_FUNC(goodbye, tschuess)
);
CINELERRA_INTERFACE_IMPLEMENT(hello, 1, english, myopen, myclose,
CINELERRA_INTERFACE_FUNC(hello, hello),
CINELERRA_INTERFACE_FUNC(goodbye, bye)
//CINELERRA_INTERFACE_FUNC(hello, hello),
//CINELERRA_INTERFACE_FUNC(goodbye, bye)
);

View file

@ -1,6 +1,6 @@
#include "plugin.h"
CINELERRA_INTERFACE(hello, 1,
CINELERRA_INTERFACE_PROTO(void, hello, (void)),
CINELERRA_INTERFACE_PROTO(void, goodbye, (const char*)),
CINELERRA_INTERFACE_PROTO(void, hello, (void))
CINELERRA_INTERFACE_PROTO(void, goodbye, (const char*))
);

View file

@ -12,20 +12,22 @@ main(int argc, char** argv)
open both try them, close them.
*/
struct hello_interface_1* hello_de =
cinelerra_interface_open ("hello_1", "german_1", sizeof(struct hello_interface_1));
if (!hello_de) CINELERRA_DIE;
TODO("macros, doing casting and typing");
hello_de->say_hello();
CINELERRA_INTERFACE_TYPE(hello, 1)* hello_de = (CINELERRA_INTERFACE_TYPE(hello, 1)*)
cinelerra_interface_open ("hello_1", "german_1", sizeof(CINELERRA_INTERFACE_TYPE(hello, 1)));
TODO("new error handling, when finished if (!hello_de) CINELERRA_DIE");
hello_de->hello();
struct hello_interface_1* hello_en =
cinelerra_interface_open ("hello_1", "english_1", sizeof(struct hello_interface_1));
if (!hello_en) CINELERRA_DIE;
// struct hello_interface_1* hello_en =
// cinelerra_interface_open ("hello_1", "english_1", sizeof(struct hello_interface_1));
// TODO if (!hello_en) CINELERRA_DIE;
hello_en->say_hello();
//hello_en->hello();
cinelerra_interface_close (hello_en);
//cinelerra_interface_close (hello_en);
cinelerra_interface_close (hello_de);
#if 0

View file

@ -1,33 +1,32 @@
#!/bin/bash
#!/bin/bash
# Copyright (C) CinelerraCV
# 2007, Christian Thaeter <ct@pipapo.org>
# Hermann Vosseler <Ichthyostega@web.de>
#
# tests/test.sh - run all defined automatic tests
# This program is free software; you can redistribute it and/or
# modify 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
# GNU General Public License for more details.
#
# Copyright (C) CinelerraCV
# 2007, Christian Thaeter <ct@pipapo.org>
#
# This program is free software; you can redistribute it and/or
# modify 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
# GNU General Public License for more details.
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
#
###################################################################
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
# TESTMODE=FULL yet unimplemented
# run all tests, PLANNED which fail count as error
#
# TESTMODE=FAST
# run only tests which recently failed
#
# TESTMODE=FIRSTFAIL
# stop testing on the first failure
export LC_ALL=C
arg0="$0"
srcdir=$(dirname "$arg0")
@ -38,7 +37,7 @@ if [ "$VALGRINDFLAGS" = 'DISABLE' ]; then
echo "valgrind explicit disabled"
else
if [ "$(which valgrind)" ]; then
valgrind="$(which valgrind) --suppressions=$srcdir/../valgrind.sup --leak-check=yes --show-reachable=yes -q $VALGRINDFLAGS"
valgrind="$(which valgrind) --leak-check=yes --show-reachable=yes -q $VALGRINDFLAGS"
ulimit -S -t 10
else
echo "no valgrind found, go without it"
@ -46,12 +45,13 @@ else
fi
echo
echo ================ $0 ================
echo ================ ${0##*/} ================
TESTCNT=0
SKIPCNT=0
FAILCNT=0
# the old testlog if existing will be used to check for previous test states
if test -f ,testlog; then
mv ,testlog ,testlog.pre
else
@ -62,10 +62,36 @@ date >,testlog
function TEST()
{
name="$1"
name="$1"
shift
cat >,cmp
echo -n "" >,out
rm -f ,send_stdin
rm -f ,expect_stdout
rm -f ,expect_stderr
while read -r line; do
cmd="${line%%:*}"
arg="${line#*: }"
expect_return=0
case $cmd in
'in')
echo "$arg" >>,send_stdin
;;
'out')
echo "$arg" >>,expect_stdout
;;
'err')
echo "$arg" >>,expect_stderr
;;
'return')
expect_return=$arg
;;
*)
echo "UNKOWN TEST COMMAND '$cmd'" 1>&2
exit
;;
esac
done
echo -n "TEST $name: "
echo -en "\nTEST $name: $* " >>,testlog
@ -92,16 +118,54 @@ function TEST()
esac
TESTCNT=$(($TESTCNT + 1))
if $valgrind $TESTBIN "$@" 2>&1 | tee ,tmp | grep -v ': \(TRACE\|INFO\|NOTICE\|WARNING\|ERR\):' | cmp ,cmp - &>/dev/null; then
fails=0
if test -f ,send_stdin; then
cat ,send_stdin | $valgrind $TESTBIN "$@" 2>,stderr >,stdout
else
$valgrind $TESTBIN "$@" 2>,stderr >,stdout
fi &>/dev/null
return=$?
echo -n >,testtmp
if test -f ,expect_stdout; then
if ! cmp ,expect_stdout ,stdout &>/dev/null; then
echo "unexpected data on stdout" >>,testtmp
grep -v ': \(TRACE\|INFO\|NOTICE\|WARNING\|ERR\):' <,stdout >,tmp
diff -ua ,expect_stdout ,tmp >>,testtmp
rm ,tmp
((fails+=1))
fi
fi
if test -f ,expect_stderr; then
if ! cmp ,expect_stderr ,stderr &>/dev/null; then
echo "unexpected data on stderr" >>,testtmp
grep -v ': \(TRACE\|INFO\|NOTICE\|WARNING\|ERR\):' <,stderr >,tmp
diff -ua ,expect_stderr ,tmp >>,testtmp
rm ,tmp
((fails+=1))
fi
fi
if test $expect_return != $return; then
echo "unexpected return value $return" >>,testtmp
((fails+=1))
fi
if test $fails -eq 0; then
echo ".. OK$MSGOK"
echo ".. OK$MSGOK" >>,testlog
else
echo ".. FAILED$MSGFAIL";
echo ".. FAILED$MSGFAIL" >>,testlog
grep -v ': \(TRACE\|INFO\|NOTICE\|WARNING\|ERR\):' <,tmp >,out
diff -ua ,cmp ,out >>,testlog
# grep 'DEBUG:\|==.*==' <,tmp >>,testlog
cat ,tmp >>,testlog
cat ,testtmp >>,testlog
rm ,testtmp
echo "stderr was:" >>,testlog
cat ,stderr >>,testlog
echo END >>,testlog
FAILCNT=$(($FAILCNT + 1))
case $TESTMODE in
@ -128,7 +192,6 @@ function RUNTESTS()
source $i
done
echo
rm ,cmp ,out ,tmp
if [ $FAILCNT = 0 ]; then
echo " ... PASSED $(($TESTCNT - $SKIPCNT)) TESTS, $SKIPCNT SKIPPED"
#rm ,testlog
@ -149,6 +212,3 @@ function TESTING()
}
RUNTESTS
# arch-tag: f4d06a47-6e17-40de-bba8-17240ae3f435

View file

@ -825,6 +825,7 @@ to get started, we create design drafts emphasizing different aspects and region
* Ichthyo focuses mainly on the Render Engine and its interconnection to the EDL, [[see this separate page|renderengine.html]]
* Cehteh works on the data backend draft, see [[this page|backend.html]]
* Some tools which don't fit somewhere else and are used everywhere are put into a [[Support Library|support_library.html]]
* [[Description of the Test System|TestSh]]
!Coding Structures
next we should //start thinking// on how to organize several aspects of the practical coding...
@ -3471,38 +3472,55 @@ Portions written by Luke Blanshard are hereby released into the public domain.
&lt;!--}}}--&gt;
</pre>
</div>
<div title="TestFacility" modifier="Ichthyostega" modified="200708120257" created="200708120134" tags="buildsys organization howto" changecount="3">
<pre>We use a very simple test facility written by Cehteh as a bash script {{{tests/test.sh}}}
Basically the target __tests__ of the build system uses the test code found in the tree below {{{./tests}}} to build some test binaries (btw scripts could be used too),
and then runs {{{test.sh}}} with the testsuite definitions.
<div title="TestSh" modifier="Ichthyostega" modified="200708170336" created="200708131509" tags="buildsys organization testsuite" changecount="7">
<pre>! The Test Script
To drive the various tests, we use the script {{{tests/test.sh}}}. All tests are run under valgrind control if available unless {{{VALGRINDFLAGS=DISABLE}}} is defined.
* The SCons buildsystem will build and run the testcode when executing the target {{{scons tests}}}.
* This test script is integrated in the automake build and will be used when {{{make check}}} is called.
''Test definitions'' are defined in files {{{000foo.test, 010bar.test, ...}}}.
Syntax is as following //(note that this are just bash scripts)//
! Options for running the Test Suite
One may define {{{TESTMODE}}} containing any one of the following strings:
* {{{FAST}}} only run tests which failed recently
* {{{FIRSTFAIL}}} abort the tests at the first failure
putting this together a very fast check (when using automake) while hacking on the source would look like:
{{{
TESTING &quot;label for sometestprogram&quot; ./sometestprogram
TEST &quot;unique annotatinon&quot; --command --line --options &lt;&lt;END
expected
output
here
END
VALGRINDFLAGS=DISABLE TESTMODE=FAST+FIRSTFAIL make check
}}}
The {{{TESTING}}} function defines {{{$TESTBIN}}} for the subsequent tests.
the {{{TEST}}} function will run {{{&quot;$TESTBIN --command --line --options&quot;}}} probably under Valgrind supervision and diff its output against expected output literally specified in the test definition (e.g. {{{&quot;expected\noutput\nhere&quot;}}}). Note that Valgrind (used in quiet mode) produces bug reports which will make the test fail, as any other unexpected output will do.
This doesnt catch all errors, notably not regressions, but is useful to do coarse checks.
Running the testsuite with everything enabled is just:
{{{
make check
}}}
! Writing Tests
Tests are written in files named {{{NNname.tests}}} in the {{{tests}}} dir, where NN is a number defining the order of the various test files, 'name' should be a descriptive name about whats going to be tested.
In a .tests file one has to define following:
* {{{TESTING &lt;description&gt; &lt;binary&gt;}}} set the program binary to be tested to &lt;binary&gt;, &lt;description&gt; should be a string which is displayed as header before running following tests
* {{{TEST &lt;description&gt; [optargs] &lt;&lt;END}}} run the previously set binary with [optargs], &lt;description&gt; is displayed when running this test. A detailed test spec must follow this command and be terminated with {{{END}}} on a single line. Test specs can contain following statements:
** {{{in: &lt;line&gt;}}} send &lt;line&gt; to stdin of the test program
** {{{out: &lt;line&gt;}}} expect &lt;line&gt; at the stdout of the test program
** {{{err: &lt;line&gt;}}} expect &lt;line&gt; at the stderr of the test program
** {{{return: &lt;status&gt;}}} expect &lt;status&gt; as exit status of the program
If no {{{out:}}} or {{{err:}}} is given, stdout and stderr are not considered as part of the test. If no {{{return:}}} is given, then 0 is expected.
------
how to organize the actual Tests into various Test collections &amp;rarr; see [[TestSuite]]
</pre>
</div>
<div title="TestSuite" modifier="Ichthyostega" modified="200708120257" created="200708120254" tags="buildsys organization testsuite" changecount="2">
<pre>For running the automatic Tests, we use Cehteh's simple [[test.sh|TestFacility]].
<div title="TestSuite" modifier="Ichthyostega" modified="200708170345" created="200708120254" tags="buildsys organization testsuite" changecount="8">
<pre>For running the automatic Tests, we use Cehteh's simple [[test.sh|TestSh]].
This page is a proposal (by Ichthyo) how the various tests could be organized.
* individual Tests are classes, doing whatsoever and however they see fit.
* individual Testcases are classes, doing whatsoever and however they see fit.
* it is up to the individual test classes to take care / handle / isolate themself form any dependencies (similar to the [[philosophy of TestNG|http://www.beust.com/weblog/archives/000082.html]])
* for each Testsuite (=distinct collection of tests) we build an executable linked against the test class objects
* Testcases are grouped together into thematic (Sub)-Testsuites. Each Testcase has an unique ID and can be tagged with several groupIDs
* for each Testsuite (=distinct collection of tests) we build an executable linked against the test class objects.
* moreover, for simple Tests, we can build separate stelf-contained executables or even use other scripts.
* when we get several Testsuites at some point in the future, we may consider building a shared lib of the test objects.
* the Testsuite executable should provide some command line magic to select individual tests
* the Testsuite executable should provide some command line magic to select individual tests.
* Top-level Testsuites or ~Test-Collections for [[test.sh|TestSh]] contain calls to the different (sub)-Suites, together with the expected results/output
</pre>
</div>
<div title="TextAreaPlugin" modifier="Jeremy" created="200601261745" tags="systemConfig" server.type="file" server.host="file:///home/ct/.homepage/home.html" server.page.revision="200601261745">