diff --git a/.gitignore b/.gitignore index 1a693c969..141d31bb7 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 000000000..09e1593c9 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,46 @@ +# Copyright (C) CinelerraCV +# 2007, Christian Thaeter +# +# 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 + diff --git a/admin/git_hooks/post-commit b/admin/git_hooks/post-commit index cf0dd5ec1..34b182a81 100755 --- a/admin/git_hooks/post-commit +++ b/admin/git_hooks/post-commit @@ -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/*" diff --git a/configure.ac b/configure.ac new file mode 100644 index 000000000..5b2512122 --- /dev/null +++ b/configure.ac @@ -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 + + 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 diff --git a/scripts/DIR_INFO b/scripts/DIR_INFO new file mode 100644 index 000000000..265ca57ac --- /dev/null +++ b/scripts/DIR_INFO @@ -0,0 +1 @@ +autotools helper scripts diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am new file mode 100644 index 000000000..7419bedf9 --- /dev/null +++ b/src/lib/Makefile.am @@ -0,0 +1,24 @@ +# Copyright (C) CinelerraCV +# 2007, Christian Thaeter +# +# 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 diff --git a/src/lib/error.c b/src/lib/error.c new file mode 100644 index 000000000..d05696c06 --- /dev/null +++ b/src/lib/error.c @@ -0,0 +1,56 @@ +/* + error.c - Cinelerra Error handling + + Copyright (C) CinelerraCV + 2007, Christian Thaeter + + 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 + +/* 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; +} diff --git a/src/lib/error.h b/src/lib/error.h new file mode 100644 index 000000000..6b8aaf753 --- /dev/null +++ b/src/lib/error.h @@ -0,0 +1,42 @@ +/* + error.h - Cinelerra Error handling + + Copyright (C) CinelerraCV + 2007, Christian Thaeter + + 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 +#include + +#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 */ diff --git a/src/lib/plugin.c b/src/lib/plugin.c index 6876674f4..ec7b3f0a6 100644 --- a/src/lib/plugin.c +++ b/src/lib/plugin.c @@ -19,6 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include +#include #include #include #include @@ -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; diff --git a/src/lib/plugin.h b/src/lib/plugin.h index 605da329c..74ab964b3 100644 --- a/src/lib/plugin.h +++ b/src/lib/plugin.h @@ -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. diff --git a/tests/00test.tests b/tests/00test.tests new file mode 100644 index 000000000..0b894982b --- /dev/null +++ b/tests/00test.tests @@ -0,0 +1,13 @@ +TESTING "test system selftest" cat + +TEST "test cat'ing stdin to stdout" < +# Hermann Vosseler +# +# 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 diff --git a/tests/errortest.c b/tests/errortest.c new file mode 100644 index 000000000..9c1ae1f12 --- /dev/null +++ b/tests/errortest.c @@ -0,0 +1,65 @@ +/* + errortest.c - test error handling + + Copyright (C) CinelerraCV + 2007, Christian Thaeter + + 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 +#include +#include + +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; +} diff --git a/tests/examples/Makefile.am b/tests/examples/Makefile.am new file mode 100644 index 000000000..5ca03150a --- /dev/null +++ b/tests/examples/Makefile.am @@ -0,0 +1,30 @@ +# Copyright (C) CinelerraCV +# 2007, Christian Thaeter +# +# 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 diff --git a/tests/examples/example_plugin.c b/tests/examples/example_plugin.c index 1a294b8bf..2f4e96a6c 100644 --- a/tests/examples/example_plugin.c +++ b/tests/examples/example_plugin.c @@ -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) ); diff --git a/tests/examples/hello_interface.h b/tests/examples/hello_interface.h index 58483e6ff..183a22c54 100644 --- a/tests/examples/hello_interface.h +++ b/tests/examples/hello_interface.h @@ -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*)) ); diff --git a/tests/examples/plugin_main.c b/tests/examples/plugin_main.c index 1902fc5fe..427f88655 100644 --- a/tests/examples/plugin_main.c +++ b/tests/examples/plugin_main.c @@ -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 diff --git a/tests/test.sh b/tests/test.sh index 30516cfde..ed8d6a35b 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -1,33 +1,32 @@ -#!/bin/bash +#!/bin/bash +# Copyright (C) CinelerraCV +# 2007, Christian Thaeter +# Hermann Vosseler # -# 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 -# -# 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 - diff --git a/wiki/index.html b/wiki/index.html index f5c12067d..7f11ae4f7 100755 --- a/wiki/index.html +++ b/wiki/index.html @@ -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. <!--}}}--> -
-
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. 
+
+
! 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 "label for sometestprogram" ./sometestprogram
-
-TEST "unique annotatinon" --command --line --options <<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 {{{"$TESTBIN --command --line --options"}}} probably under Valgrind supervision and diff its output against expected output literally specified in the test definition (e.g. {{{"expected\noutput\nhere"}}}). 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 <description> <binary>}}} set the program binary to be tested to <binary>, <description> should be a string which is displayed as header before running following tests
+* {{{TEST <description> [optargs] <<END}}} run the previously set binary with [optargs], <description> 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: <line>}}} send <line> to stdin of the test program
+** {{{out: <line>}}} expect <line> at the stdout of the test program
+** {{{err: <line>}}} expect <line> at the stderr of the test program
+** {{{return: <status>}}} expect <status> 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 &rarr; see [[TestSuite]]
 
-
-
For running the automatic Tests, we use Cehteh's simple [[test.sh|TestFacility]].
+
+
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