Added unit test framework, and some initial unit tests.
authorAndrej Kacian <ticho@claws-mail.org>
Fri, 31 Aug 2018 11:48:30 +0000 (13:48 +0200)
committerAndrej Kacian <ticho@claws-mail.org>
Fri, 31 Aug 2018 12:37:46 +0000 (14:37 +0200)
99 files changed:
.gitignore
Makefile.am
appdata/Makefile.am
config/Makefile.am
config/test-driver [new file with mode: 0755]
configure.ac
doc/Makefile.am
doc/man/Makefile.am
m4/Makefile.am
manual/Makefile.am
manual/de/Makefile.am
manual/de/dist/Makefile.am
manual/de/dist/html/Makefile.am
manual/de/dist/pdf/Makefile.am
manual/de/dist/ps/Makefile.am
manual/de/dist/txt/Makefile.am
manual/dist/Makefile.am
manual/dist/html/Makefile.am
manual/dist/pdf/Makefile.am
manual/dist/ps/Makefile.am
manual/dist/txt/Makefile.am
manual/dtd/Makefile.am
manual/es/Makefile.am
manual/es/dist/Makefile.am
manual/es/dist/html/Makefile.am
manual/es/dist/pdf/Makefile.am
manual/es/dist/ps/Makefile.am
manual/es/dist/txt/Makefile.am
manual/fr/Makefile.am
manual/fr/dist/Makefile.am
manual/fr/dist/html/Makefile.am
manual/fr/dist/pdf/Makefile.am
manual/fr/dist/ps/Makefile.am
manual/fr/dist/txt/Makefile.am
manual/pl/Makefile.am
manual/pl/dist/Makefile.am
manual/pl/dist/html/Makefile.am
manual/pl/dist/pdf/Makefile.am
manual/pl/dist/ps/Makefile.am
manual/pl/dist/txt/Makefile.am
src/Makefile.am
src/common/Makefile.am
src/common/tests/Makefile.am [new file with mode: 0644]
src/common/tests/codeconv_test.c [new file with mode: 0644]
src/common/tests/data/empty.xml [new file with mode: 0644]
src/common/tests/md5_test.c [new file with mode: 0644]
src/common/tests/mock_prefs_common_get_use_shred.h [new file with mode: 0644]
src/common/tests/pkcs5_pbkdf2_test.c [new file with mode: 0644]
src/common/tests/xml_test.c [new file with mode: 0644]
src/etpan/Makefile.am
src/gtk/Makefile.am
src/plugins/Makefile.am
src/plugins/acpi_notifier/Makefile.am
src/plugins/address_keeper/Makefile.am
src/plugins/archive/Makefile.am
src/plugins/att_remover/Makefile.am
src/plugins/attachwarner/Makefile.am
src/plugins/bogofilter/Makefile.am
src/plugins/bsfilter/Makefile.am
src/plugins/clamd/Makefile.am
src/plugins/clamd/libclamd/Makefile.am
src/plugins/demo/Makefile.am
src/plugins/dillo/Makefile.am
src/plugins/fancy/Makefile.am
src/plugins/fetchinfo/Makefile.am
src/plugins/gdata/Makefile.am
src/plugins/libravatar/Makefile.am
src/plugins/mailmbox/Makefile.am
src/plugins/managesieve/Makefile.am
src/plugins/newmail/Makefile.am
src/plugins/notification/Makefile.am
src/plugins/notification/gtkhotkey/Makefile.am
src/plugins/pdf_viewer/Makefile.am
src/plugins/perl/Makefile.am
src/plugins/perl/tools/Makefile.am
src/plugins/pgpcore/Makefile.am
src/plugins/pgpinline/Makefile.am
src/plugins/pgpmime/Makefile.am
src/plugins/python/Makefile.am
src/plugins/python/examples/Makefile.am
src/plugins/rssyl/Makefile.am
src/plugins/rssyl/libfeed/Makefile.am
src/plugins/rssyl/libfeed/tests/Makefile.am [new file with mode: 0644]
src/plugins/rssyl/libfeed/tests/date_test.c [new file with mode: 0644]
src/plugins/rssyl/libfeed/tests/feed_test.c [new file with mode: 0644]
src/plugins/rssyl/libfeed/tests/mock_procheader_date_parse.h [new file with mode: 0644]
src/plugins/rssyl/strutils.h
src/plugins/rssyl/tests/Makefile.am [new file with mode: 0644]
src/plugins/rssyl/tests/strutils_test.c [new file with mode: 0644]
src/plugins/smime/Makefile.am
src/plugins/spam_report/Makefile.am
src/plugins/spamassassin/Makefile.am
src/plugins/tnef_parse/Makefile.am
src/plugins/vcalendar/Makefile.am
src/tests/Makefile.am [new file with mode: 0644]
src/tests/entity_test.c [new file with mode: 0644]
src/tests/mock_debug_print.h [new file with mode: 0644]
tests.mk [new file with mode: 0644]
tools/Makefile.am

index 0cb7868..bebe946 100644 (file)
@@ -102,6 +102,7 @@ Makefile.in
 /src/matcher_parser_parse.c
 /src/matcher_parser_parse.h
 /src/plugins/notification/gtkhotkey/x11/.dirstamp
+*_test
 /src/quote_fmt_lex.c
 /src/quote_fmt_parse.c
 /src/quote_fmt_parse.h
index 3fdb4aa..cbbe2f2 100644 (file)
@@ -3,6 +3,10 @@
 # terms of the General Public License version 3 (or later).
 # See COPYING file for license details.
 
+if BUILD_TESTS
+include $(top_srcdir)/tests.mk
+endif
+
 ACLOCAL_AMFLAGS = -I m4
 AUTOMAKE_OPTIONS = dist-bzip2 dist-xz
 
index 15066a2..30e47f5 100644 (file)
@@ -40,3 +40,5 @@ appdata_DATA = $(appdata_in_files:.xml.in=.xml)
 
 EXTRA_DIST = $(appdata_DATA) $(appdata_in_files)
 
+
+.PHONY: test
index e69de29..d4b3f0a 100644 (file)
@@ -0,0 +1,2 @@
+
+.PHONY: test
diff --git a/config/test-driver b/config/test-driver
new file mode 100755 (executable)
index 0000000..0218a01
--- /dev/null
@@ -0,0 +1,148 @@
+#! /bin/sh
+# test-driver - basic testsuite driver script.
+
+scriptversion=2016-01-11.22; # UTC
+
+# Copyright (C) 2011-2017 Free Software Foundation, Inc.
+#
+# 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, 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, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+# Make unconditional expansion of undefined variables an error.  This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+usage_error ()
+{
+  echo "$0: $*" >&2
+  print_usage >&2
+  exit 2
+}
+
+print_usage ()
+{
+  cat <<END
+Usage:
+  test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
+              [--expect-failure={yes|no}] [--color-tests={yes|no}]
+              [--enable-hard-errors={yes|no}] [--]
+              TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
+The '--test-name', '--log-file' and '--trs-file' options are mandatory.
+END
+}
+
+test_name= # Used for reporting.
+log_file=  # Where to save the output of the test script.
+trs_file=  # Where to save the metadata of the test run.
+expect_failure=no
+color_tests=no
+enable_hard_errors=yes
+while test $# -gt 0; do
+  case $1 in
+  --help) print_usage; exit $?;;
+  --version) echo "test-driver $scriptversion"; exit $?;;
+  --test-name) test_name=$2; shift;;
+  --log-file) log_file=$2; shift;;
+  --trs-file) trs_file=$2; shift;;
+  --color-tests) color_tests=$2; shift;;
+  --expect-failure) expect_failure=$2; shift;;
+  --enable-hard-errors) enable_hard_errors=$2; shift;;
+  --) shift; break;;
+  -*) usage_error "invalid option: '$1'";;
+   *) break;;
+  esac
+  shift
+done
+
+missing_opts=
+test x"$test_name" = x && missing_opts="$missing_opts --test-name"
+test x"$log_file"  = x && missing_opts="$missing_opts --log-file"
+test x"$trs_file"  = x && missing_opts="$missing_opts --trs-file"
+if test x"$missing_opts" != x; then
+  usage_error "the following mandatory options are missing:$missing_opts"
+fi
+
+if test $# -eq 0; then
+  usage_error "missing argument"
+fi
+
+if test $color_tests = yes; then
+  # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
+  red='\e[0;31m' # Red.
+  grn='\e[0;32m' # Green.
+  lgn='\e[1;32m' # Light green.
+  blu='\e[1;34m' # Blue.
+  mgn='\e[0;35m' # Magenta.
+  std='\e[m'     # No color.
+else
+  red= grn= lgn= blu= mgn= std=
+fi
+
+do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
+trap "st=129; $do_exit" 1
+trap "st=130; $do_exit" 2
+trap "st=141; $do_exit" 13
+trap "st=143; $do_exit" 15
+
+# Test script is run here.
+"$@" >$log_file 2>&1
+estatus=$?
+
+if test $enable_hard_errors = no && test $estatus -eq 99; then
+  tweaked_estatus=1
+else
+  tweaked_estatus=$estatus
+fi
+
+case $tweaked_estatus:$expect_failure in
+  0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
+  0:*)   col=$grn res=PASS  recheck=no  gcopy=no;;
+  77:*)  col=$blu res=SKIP  recheck=no  gcopy=yes;;
+  99:*)  col=$mgn res=ERROR recheck=yes gcopy=yes;;
+  *:yes) col=$lgn res=XFAIL recheck=no  gcopy=yes;;
+  *:*)   col=$red res=FAIL  recheck=yes gcopy=yes;;
+esac
+
+# Report the test outcome and exit status in the logs, so that one can
+# know whether the test passed or failed simply by looking at the '.log'
+# file, without the need of also peaking into the corresponding '.trs'
+# file (automake bug#11814).
+echo "$res $test_name (exit status: $estatus)" >>$log_file
+
+# Report outcome to console.
+echo "${col}${res}${std}: $test_name"
+
+# Register the test result, and other relevant metadata.
+echo ":test-result: $res" > $trs_file
+echo ":global-test-result: $res" >> $trs_file
+echo ":recheck: $recheck" >> $trs_file
+echo ":copy-in-global-log: $gcopy" >> $trs_file
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
index edf7767..50766e1 100644 (file)
@@ -296,6 +296,10 @@ AC_ARG_ENABLE(svg,
         [  --disable-svg                   Do not build SVG support],
         [enable_svg=$enableval], [enable_svg=yes])
 
+AC_ARG_ENABLE(tests,
+                               [ --enable-tests                   Build unit tests],
+                               [enable_tests=$enableval], [enable_tests=no])
+
 manualdir='${docdir}/manual'
 AC_ARG_WITH(manualdir,
        [  --with-manualdir=DIR    Manual directory],
@@ -965,6 +969,14 @@ else
 fi
 AM_CONDITIONAL(CLAWS_VALGRIND, test x"$enable_valgrind" = x"yes")
 
+AC_MSG_CHECKING([whether to build unit tests])
+if test x$enable_tests = xyes; then
+       AC_MSG_RESULT(yes)
+else
+       AC_MSG_RESULT(no)
+fi
+AM_CONDITIONAL(BUILD_TESTS, test "x$enable_tests" = "xyes")
+
 dnl *************************
 dnl ** section for plugins **
 dnl *************************
@@ -1097,7 +1109,7 @@ AC_ARG_ENABLE(vcalendar-plugin,
 
 dnl disabled by default
 AC_ARG_ENABLE(demo-plugin,
-               [  --enable-demo-plugin         Build demo plugin],
+               [  --enable-demo-plugin            Build demo plugin],
                [enable_demo_plugin=$enableval], [enable_demo_plugin=no])
 
 
@@ -2029,6 +2041,7 @@ src/common/version.h
 src/Makefile
 src/common/Makefile
 src/common/passcrypt.h
+src/common/tests/Makefile
 src/gtk/Makefile
 src/etpan/Makefile
 src/plugins/Makefile
@@ -2061,12 +2074,15 @@ src/plugins/pgpcore/Makefile
 src/plugins/pgpmime/Makefile
 src/plugins/pgpinline/Makefile
 src/plugins/rssyl/Makefile
+src/plugins/rssyl/tests/Makefile
 src/plugins/rssyl/libfeed/Makefile
+src/plugins/rssyl/libfeed/tests/Makefile
 src/plugins/smime/Makefile
 src/plugins/spamassassin/Makefile
 src/plugins/spam_report/Makefile
 src/plugins/tnef_parse/Makefile
 src/plugins/vcalendar/Makefile
+src/tests/Makefile
 doc/Makefile
 doc/man/Makefile
 tools/Makefile
@@ -2120,6 +2136,7 @@ echo "Generic UMPC code  : $enable_generic_umpc"
 echo "SVG support        : $enable_svg"
 echo "Config dir         : $ac_cv_with_config_dir"
 echo "Password crypto    : $pwd_crypto"
+echo "Unit tests         : $enable_tests"
 
 echo "Plugins"
 echo "   Built:"
index 5beeea0..a808617 100644 (file)
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS = man
+
+.PHONY: test
index 54e06ae..c2c91a4 100644 (file)
@@ -7,3 +7,5 @@ man_MANS = \
      claws-mail.1
 
 EXTRA_DIST = $(man_MANS)
+
+.PHONY: test
index b409865..be424a8 100644 (file)
@@ -14,3 +14,5 @@ EXTRA_DIST = codeset.m4 glibc21.m4 intdiv0.m4 intmax.m4 inttypes.m4 inttypes_h.m
        missing/gdk-pixbuf.m4 \
        missing/gettext.m4 \
        missing/gpgme.m4
+
+.PHONY: test
index 179cd66..32f2495 100644 (file)
@@ -21,3 +21,5 @@ EXTRA_DIST = \
        plugins.xml \
        starting.xml \
        claws-mail-manual.xml
+
+.PHONY: test
index 00f1ca8..1a605a6 100644 (file)
@@ -21,3 +21,5 @@ EXTRA_DIST = \
        plugins.xml \
        starting.xml \
        claws-mail-manual.xml
+
+.PHONY: test
index 9bff2bd..c19a2fd 100644 (file)
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS=html pdf ps txt
+
+.PHONY: test
index 3560fd4..9b09880 100644 (file)
@@ -31,3 +31,5 @@ maintainer-clean:
        -rm claws-mail-manual.html
        -rm claws-mail-manual.html.raw
 endif
+
+.PHONY: test
index 050a7d9..c5a3b9e 100644 (file)
@@ -27,3 +27,5 @@ claws-mail-manual.pdf: \
 maintainer-clean:
        -rm claws-mail-manual.pdf claws-mail-manual.fo claws-mail-manual.xsl
 endif
+
+.PHONY: test
index 96a9069..8c2ca03 100644 (file)
@@ -27,3 +27,5 @@ claws-mail-manual.ps: \
 maintainer-clean:
        -rm claws-mail-manual.ps
 endif
+
+.PHONY: test
index 020fbf2..26017b6 100644 (file)
@@ -27,3 +27,5 @@ claws-mail-manual.txt: \
 maintainer-clean:
        -rm claws-mail-manual.txt
 endif
+
+.PHONY: test
index 9bff2bd..c19a2fd 100644 (file)
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS=html pdf ps txt
+
+.PHONY: test
index 3f66e1c..cf1d577 100644 (file)
@@ -31,3 +31,5 @@ maintainer-clean:
        -rm claws-mail-manual.html
        -rm claws-mail-manual.html.raw
 endif
+
+.PHONY: test
index 2a78f05..10329e2 100644 (file)
@@ -27,3 +27,5 @@ claws-mail-manual.pdf: \
 maintainer-clean:
        -rm claws-mail-manual.pdf claws-mail-manual.fo claws-mail-manual.xsl
 endif
+
+.PHONY: test
index d4f067c..0c82b57 100644 (file)
@@ -27,3 +27,5 @@ claws-mail-manual.ps: \
 maintainer-clean:
        -rm claws-mail-manual.ps
 endif
+
+.PHONY: test
index 34ddc40..afda992 100644 (file)
@@ -27,3 +27,5 @@ claws-mail-manual.txt: \
 maintainer-clean:
        -rm claws-mail-manual.txt
 endif
+
+.PHONY: test
index 0c134f1..024b07f 100644 (file)
@@ -5,3 +5,5 @@
 
 EXTRA_DIST= \
        manual.dsl  sdocbook.dtd
+
+.PHONY: test
index 00f1ca8..1a605a6 100644 (file)
@@ -21,3 +21,5 @@ EXTRA_DIST = \
        plugins.xml \
        starting.xml \
        claws-mail-manual.xml
+
+.PHONY: test
index 9bff2bd..c19a2fd 100644 (file)
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS=html pdf ps txt
+
+.PHONY: test
index 155d8f9..05cec3a 100644 (file)
@@ -31,3 +31,5 @@ maintainer-clean:
        -rm claws-mail-manual.html
        -rm claws-mail-manual.html.raw
 endif
+
+.PHONY: test
index 4382322..ac779fb 100644 (file)
@@ -27,3 +27,5 @@ claws-mail-manual.pdf: \
 maintainer-clean:
        -rm claws-mail-manual.pdf claws-mail-manual.fo claws-mail-manual.xsl
 endif
+
+.PHONY: test
index 7b26017..fa3e936 100644 (file)
@@ -27,3 +27,5 @@ claws-mail-manual.ps: \
 maintainer-clean:
        -rm claws-mail-manual.ps
 endif
+
+.PHONY: test
index d3c7b61..8ced198 100644 (file)
@@ -27,3 +27,5 @@ claws-mail-manual.txt: \
 maintainer-clean:
        -rm claws-mail-manual.txt
 endif
+
+.PHONY: test
index 00f1ca8..1a605a6 100644 (file)
@@ -21,3 +21,5 @@ EXTRA_DIST = \
        plugins.xml \
        starting.xml \
        claws-mail-manual.xml
+
+.PHONY: test
index 9bff2bd..c19a2fd 100644 (file)
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS=html pdf ps txt
+
+.PHONY: test
index a44d39d..0a04981 100644 (file)
@@ -31,3 +31,5 @@ maintainer-clean:
        -rm claws-mail-manual.html
        -rm claws-mail-manual.html.raw
 endif
+
+.PHONY: test
index b7a8a53..2c8f1c3 100644 (file)
@@ -27,3 +27,5 @@ claws-mail-manual.pdf: \
 maintainer-clean:
        -rm claws-mail-manual.pdf claws-mail-manual.fo claws-mail-manual.xsl
 endif
+
+.PHONY: test
index 53f5bdb..bb9a6da 100644 (file)
@@ -27,3 +27,5 @@ claws-mail-manual.ps: \
 maintainer-clean:
        -rm claws-mail-manual.ps
 endif
+
+.PHONY: test
index 957b1bf..1647679 100644 (file)
@@ -27,3 +27,5 @@ claws-mail-manual.txt: \
 maintainer-clean:
        -rm claws-mail-manual.txt
 endif
+
+.PHONY: test
index 00f1ca8..1a605a6 100644 (file)
@@ -21,3 +21,5 @@ EXTRA_DIST = \
        plugins.xml \
        starting.xml \
        claws-mail-manual.xml
+
+.PHONY: test
index 9bff2bd..c19a2fd 100644 (file)
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS=html pdf ps txt
+
+.PHONY: test
index c1f3ef6..680e4a4 100644 (file)
@@ -31,3 +31,5 @@ maintainer-clean:
        -rm claws-mail-manual.html
        -rm claws-mail-manual.html.raw
 endif
+
+.PHONY: test
index 02eec0b..a599ace 100644 (file)
@@ -27,3 +27,5 @@ claws-mail-manual.pdf: \
 maintainer-clean:
        -rm claws-mail-manual.pdf claws-mail-manual.fo claws-mail-manual.xsl
 endif
+
+.PHONY: test
index 48a27df..64ad9c0 100644 (file)
@@ -27,3 +27,5 @@ claws-mail-manual.ps: \
 maintainer-clean:
        -rm claws-mail-manual.ps
 endif
+
+.PHONY: test
index 31c051d..17f970f 100644 (file)
@@ -27,3 +27,5 @@ claws-mail-manual.txt: \
 maintainer-clean:
        -rm claws-mail-manual.txt
 endif
+
+.PHONY: test
index 30e85a4..9844f30 100644 (file)
@@ -11,7 +11,11 @@ etpan_dir =
 etpan_library = 
 endif
 
-SUBDIRS = common gtk $(etpan_dir) . plugins 
+SUBDIRS = common gtk $(etpan_dir) . plugins
+if BUILD_TESTS
+include $(top_srcdir)/tests.mk
+SUBDIRS += tests
+endif
 
 bin_PROGRAMS = claws-mail
 install-exec-hook:
index 56b6cdb..5c4f249 100644 (file)
@@ -3,6 +3,11 @@
 # terms of the General Public License version 3 (or later).
 # See COPYING file for license details.
 
+if BUILD_TESTS
+include $(top_srcdir)/tests.mk
+SUBDIRS = . tests
+endif
+
 PLUGINDIR = $(pkglibdir)/plugins/
 DESKTOPFILEPATH=$(datadir)/applications/claws-mail.desktop
 
@@ -98,4 +103,3 @@ libclawscommon_la_LIBADD = \
 
 EXTRA_DIST = \
        version.h.in
-
diff --git a/src/common/tests/Makefile.am b/src/common/tests/Makefile.am
new file mode 100644 (file)
index 0000000..7b18f88
--- /dev/null
@@ -0,0 +1,31 @@
+include $(top_srcdir)/tests.mk
+
+common_ldadd = \
+       $(GLIB_LIBS)
+
+AM_CPPFLAGS = \
+       $(GLIB_CFLAGS) \
+       -DLOCALEDIR=\""$(localedir)"\" \
+       -DPLUGINDIR=\"$(PLUGINDIR)\" \
+       -I$(top_srcdir)/src \
+       -I..
+
+TEST_PROGS += xml_test
+xml_test_SOURCES = xml_test.c
+xml_test_LDADD = $(common_ldadd) ../xml.o ../stringtable.o ../utils.o ../codeconv.o ../quoted-printable.o ../unmime.o
+
+TEST_PROGS += codeconv_test
+codeconv_test_SOURCES = codeconv_test.c
+codeconv_test_LDADD = $(common_ldadd) ../codeconv.o ../utils.o ../quoted-printable.o ../unmime.o
+
+TEST_PROGS += md5_test
+md5_test_SOURCES = md5_test.c
+md5_test_LDADD = $(common_ldadd) ../md5.o
+
+TEST_PROGS += pkcs5_pbkdf2_test
+pkcs5_pbkdf2_test_SOURCES = pkcs5_pbkdf2_test.c
+pkcs5_pbkdf2_test_LDADD = $(common_ldadd) ../pkcs5_pbkdf2.o
+
+noinst_PROGRAMS = $(TEST_PROGS)
+
+.PHONY: test
diff --git a/src/common/tests/codeconv_test.c b/src/common/tests/codeconv_test.c
new file mode 100644 (file)
index 0000000..3b93eae
--- /dev/null
@@ -0,0 +1,101 @@
+#include <glib.h>
+
+#include "codeconv.h"
+
+#include "mock_prefs_common_get_use_shred.h"
+
+struct td {
+       gchar *pre; /* Input string */
+       gchar *post; /* Expected output */
+};
+
+struct td from_utf8_empty = { "", "" };
+/* TODO: more tests */
+
+struct td to_utf8_empty = { "", "" };
+/* TODO: more tests */
+
+static void
+test_filename_from_utf8_null()
+{
+       if (!g_test_undefined())
+               return;
+
+       if (g_test_subprocess()) {
+               gchar *out;
+
+               out = conv_filename_from_utf8(NULL);
+               g_assert_null(out);
+               return;
+       }
+
+       g_test_trap_subprocess(NULL, 0, 0);
+       g_test_trap_assert_stdout("*Condition*failed*");
+       g_test_trap_assert_passed();
+}
+
+static void
+test_filename_from_utf8(gconstpointer user_data)
+{
+       struct td *data = (struct td *)user_data;
+
+       if (!g_test_undefined())
+               return;
+
+       if (g_test_subprocess()) {
+               gchar *out;
+
+               out = conv_filename_from_utf8(data->pre);
+               g_assert_cmpstr(out, ==, data->post);
+
+               g_free(out);
+               return;
+       }
+
+       g_test_trap_subprocess(NULL, 0, 0);
+       g_test_trap_assert_passed();
+}
+
+static void
+test_filename_to_utf8(gconstpointer user_data)
+{
+       struct td *data = (struct td *)user_data;
+
+       if (!g_test_undefined())
+               return;
+
+       if (g_test_subprocess()) {
+               gchar *out;
+
+               out = conv_filename_to_utf8(data->pre);
+               g_assert_cmpstr(out, ==, data->post);
+
+               g_free(out);
+               return;
+       }
+
+       g_test_trap_subprocess(NULL, 0, 0);
+       g_test_trap_assert_passed();
+}
+
+int
+main(int argc, char *argv[])
+{
+       g_test_init(&argc, &argv, NULL);
+
+       g_test_add_func("/common/codeconv/filename_from_utf8/null",
+                       test_filename_from_utf8_null);
+       g_test_add_data_func("/common/codeconv/filename_from_utf8/empty",
+                       &from_utf8_empty,
+                       test_filename_from_utf8);
+
+       g_test_add_func("/common/codeconv/filename_to_utf8/null",
+                       test_filename_from_utf8_null);
+       g_test_add_data_func("/common/codeconv/filename_to_utf8/empty",
+                       &to_utf8_empty,
+                       test_filename_to_utf8);
+
+       /* TODO: more tests */
+
+       return g_test_run();
+}
diff --git a/src/common/tests/data/empty.xml b/src/common/tests/data/empty.xml
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/common/tests/md5_test.c b/src/common/tests/md5_test.c
new file mode 100644 (file)
index 0000000..e78d118
--- /dev/null
@@ -0,0 +1,256 @@
+#include <glib.h>
+
+#include <common/md5.h>
+
+struct td_digest {
+       gchar *input;
+       gchar *expected_output;
+};
+
+struct td_digest td_rfc1321_1 = { "", "d41d8cd98f00b204e9800998ecf8427e" };
+struct td_digest td_rfc1321_2 = { "a", "0cc175b9c0f1b6a831c399e269772661" };
+struct td_digest td_rfc1321_3 = { "abc", "900150983cd24fb0d6963f7d28e17f72" };
+struct td_digest td_rfc1321_4 = { "message digest", "f96b697d7cb7938d525a2f31aaf161d0" };
+struct td_digest td_rfc1321_5 = { "abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b" };
+struct td_digest td_rfc1321_6 = { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "d174ab98d277d9f5a5611c2c9f419d9f" };
+struct td_digest td_rfc1321_7 = { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a" };
+
+struct td_hmac {
+       gchar *key;
+       int key_len;
+       gchar *data;
+       int data_len;
+       gchar *expected_output;
+};
+
+struct td_hmac td_hmac_null_key = {
+       NULL, 50,
+       "", 0,
+       ""
+};
+struct td_hmac td_hmac_negative_key_length = {
+       "", -1,
+       "", 0,
+       ""
+};
+struct td_hmac td_hmac_null_data = {
+       "", 0,
+       NULL, 50,
+       ""
+};
+struct td_hmac td_hmac_negative_data_length = {
+       "abc", 3,
+       "", -1,
+       "",
+};
+
+struct td_hmac td_rfc2202_1 = {
+       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 16,
+       "Hi There", 8,
+       "9294727a3638bb1c13f48ef8158bfc9d"
+};
+struct td_hmac td_rfc2202_2 = {
+       "Jefe", 4,
+       "what do ya want for nothing?", 28,
+       "750c783e6ab0b503eaa86e310a5db738"
+};
+struct td_hmac td_rfc2202_3 = {
+       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 16,
+       "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", 50,
+       "56be34521d144c88dbb8c733f0e8b3f6"
+};
+struct td_hmac td_rfc2202_4 = {
+       "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25,
+       "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", 50,
+       "697eaf0aca3a3aea3a75164746ffaa79"
+};
+struct td_hmac td_rfc2202_5 = {
+       "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", 16,
+       "Test With Truncation", 20,
+       "56461ef2342edc00f9bab995690efd4c"
+};
+struct td_hmac td_rfc2202_6 = {
+       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80,
+       "Test Using Larger Than Block-Size Key - Hash Key First", 54,
+       "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd"
+};
+struct td_hmac td_rfc2202_7 = {
+       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80,
+       "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73,
+       "6f630fad67cda0ee1fb1f562db3aa53e"
+};
+
+static void
+test_md5_hex_digest_null_input(void)
+{
+       char outbuf[33];
+
+       outbuf[0] = '\0';
+
+       if (!g_test_undefined())
+               return;
+
+       if (g_test_subprocess()) {
+               md5_hex_digest(outbuf, NULL);
+               return;
+       }
+
+       g_test_trap_subprocess(NULL, 0, 0);
+       g_test_trap_assert_failed();
+       g_test_trap_assert_stderr("*CRITICAL*md5_hex_digest: assertion*failed*");
+       g_assert_cmpint(outbuf[0], ==, '\0');
+}
+
+static void
+test_md5_hex_digest_null_output(void)
+{
+       if (!g_test_undefined())
+               return;
+
+       if (g_test_subprocess()) {
+               md5_hex_digest(NULL, "");
+               return;
+       }
+
+       g_test_trap_subprocess(NULL, 0, 0);
+       g_test_trap_assert_failed();
+       g_test_trap_assert_stderr("*CRITICAL*md5_hex_digest: assertion*failed*");
+}
+
+static void
+test_md5_hex_digest(gconstpointer user_data)
+{
+       char outbuf[33];
+       struct td_digest *data = (struct td_digest *)user_data;
+
+       md5_hex_digest(outbuf, data->input);
+
+       g_assert_cmpint(outbuf[32], ==, '\0');
+       g_assert_cmpstr(outbuf, ==, data->expected_output);
+}
+
+static void
+test_md5_hex_hmac_null_output(void)
+{
+       if (!g_test_undefined())
+               return;
+
+       if (g_test_subprocess()) {
+               md5_hex_hmac(NULL, "", 0, "", 0);
+               return;
+       }
+
+       g_test_trap_subprocess(NULL, 0, 0);
+       g_test_trap_assert_failed();
+       g_test_trap_assert_stderr("*CRITICAL*md5_hex_hmac: assertion*failed*");
+}
+
+/* We expect all test cases using this function to fail with
+ * failed assertion */
+static void
+test_md5_hex_hmac_fails(gconstpointer user_data)
+{
+       char outbuf[33];
+       struct td_hmac *data = (struct td_hmac *)user_data;
+
+       if (!g_test_undefined())
+               return;
+
+       if (g_test_subprocess()) {
+               md5_hex_hmac(outbuf,
+                               data->data, data->data_len,
+                               data->key, data->key_len);
+               return;
+       }
+
+       g_test_trap_subprocess(NULL, 0, 0);
+       g_test_trap_assert_failed();
+       g_test_trap_assert_stderr("*CRITICAL*md5_hex_hmac: assertion*failed*");
+}
+
+static void
+test_md5_hex_hmac(gconstpointer user_data)
+{
+       char outbuf[33];
+       struct td_hmac *data = (struct td_hmac *)user_data;
+
+       md5_hex_hmac(outbuf,
+                       data->data, data->data_len,
+                       data->key, data->key_len);
+
+       g_assert_cmpint(outbuf[32], ==, '\0');
+       g_assert_cmpstr(outbuf, ==, data->expected_output);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+       g_test_init(&argc, &argv, NULL);
+
+       g_test_add_func("/common/md5/hex_digest/null_input",
+                       test_md5_hex_digest_null_input);
+       g_test_add_func("/common/md5/hex_digest/null_output",
+                       test_md5_hex_digest_null_output);
+
+       g_test_add_data_func("/common/md5/hex_digest/rfc1321_1",
+                       &td_rfc1321_1,
+                       test_md5_hex_digest);
+       g_test_add_data_func("/common/md5/hex_digest/rfc1321_2",
+                       &td_rfc1321_2,
+                       test_md5_hex_digest);
+       g_test_add_data_func("/common/md5/hex_digest/rfc1321_3",
+                       &td_rfc1321_3,
+                       test_md5_hex_digest);
+       g_test_add_data_func("/common/md5/hex_digest/rfc1321_4",
+                       &td_rfc1321_4,
+                       test_md5_hex_digest);
+       g_test_add_data_func("/common/md5/hex_digest/rfc1321_5",
+                       &td_rfc1321_5,
+                       test_md5_hex_digest);
+       g_test_add_data_func("/common/md5/hex_digest/rfc1321_6",
+                       &td_rfc1321_6,
+                       test_md5_hex_digest);
+       g_test_add_data_func("/common/md5/hex_digest/rfc1321_7",
+                       &td_rfc1321_7,
+                       test_md5_hex_digest);
+
+       g_test_add_data_func("/common/md5/hex_hmac/null_key",
+                       &td_hmac_null_key,
+                       test_md5_hex_hmac_fails);
+       g_test_add_data_func("/common/md5/hex_hmac/negative_key_length",
+                       &td_hmac_negative_key_length,
+                       test_md5_hex_hmac_fails);
+       g_test_add_data_func("/common/md5/hex_hmac/null_data",
+                       &td_hmac_null_data,
+                       test_md5_hex_hmac_fails);
+       g_test_add_data_func("/common/md5/hex_hmac/negative_data_length",
+                       &td_hmac_negative_data_length,
+                       test_md5_hex_hmac_fails);
+       g_test_add_func("/common/md5/hex_hmac/null_output",
+                       test_md5_hex_hmac_null_output);
+
+       g_test_add_data_func("/common/md5/hex_hmac/rfc2202_1",
+                       &td_rfc2202_1,
+                       test_md5_hex_hmac);
+       g_test_add_data_func("/common/md5/hex_hmac/rfc2202_2",
+                       &td_rfc2202_2,
+                       test_md5_hex_hmac);
+       g_test_add_data_func("/common/md5/hex_hmac/rfc2202_3",
+                       &td_rfc2202_3,
+                       test_md5_hex_hmac);
+       g_test_add_data_func("/common/md5/hex_hmac/rfc2202_4",
+                       &td_rfc2202_4,
+                       test_md5_hex_hmac);
+       g_test_add_data_func("/common/md5/hex_hmac/rfc2202_5",
+                       &td_rfc2202_5,
+                       test_md5_hex_hmac);
+       g_test_add_data_func("/common/md5/hex_hmac/rfc2202_6",
+                       &td_rfc2202_6,
+                       test_md5_hex_hmac);
+       g_test_add_data_func("/common/md5/hex_hmac/rfc2202_7",
+                       &td_rfc2202_7,
+                       test_md5_hex_hmac);
+
+       return g_test_run();
+}
diff --git a/src/common/tests/mock_prefs_common_get_use_shred.h b/src/common/tests/mock_prefs_common_get_use_shred.h
new file mode 100644 (file)
index 0000000..a216cbd
--- /dev/null
@@ -0,0 +1,5 @@
+gboolean prefs_common_get_use_shred(void)
+{
+       return FALSE;
+}
+
diff --git a/src/common/tests/pkcs5_pbkdf2_test.c b/src/common/tests/pkcs5_pbkdf2_test.c
new file mode 100644 (file)
index 0000000..3f7a451
--- /dev/null
@@ -0,0 +1,121 @@
+#include <glib.h>
+
+#include <common/pkcs5_pbkdf2.h>
+
+struct td {
+       gchar *input;
+       size_t input_length;
+       gchar *salt;
+       size_t salt_length;
+       size_t length;
+       guint rounds;
+       gint expected_return;
+       gchar *expected_output;
+};
+
+/* Test vectors from RFC 6070 */
+struct td td_rfc6070_1 = { "password", 8,
+       "salt", 4,
+       20, 1, 0,
+       "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6" };
+struct td td_rfc6070_2 = { "password", 8,
+       "salt", 4,
+       20, 2, 0,
+       "\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57" };
+struct td td_rfc6070_3 = { "password", 8,
+       "salt", 4,
+       20, 4096, 0,
+       "\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1" };
+struct td td_rfc6070_4 = { "password", 8,
+       "salt", 4,
+       20, 16777216, 0,
+       "\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84" };
+struct td td_rfc6070_5 = { "passwordPASSWORDpassword", 24,
+       "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
+       25, 4096, 0,
+       "\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8\xd8\x36\x62\xc0\xe4\x4a\x8b\x29\x1a\x96\x4c\xf2\xf0\x70\x38" };
+struct td td_rfc6070_6 = { "pass\0word", 9,
+       "sa\0lt", 5,
+       16, 4096, 0,
+       "\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37\xd7\xf0\x34\x25\xe0\xc3" };
+
+struct td td_zero_rounds = { "abc", 3, "abc", 3, 3, 0, -1, "" };
+struct td td_zero_output_length = { "abc", 3, "abc", 3, 0, 1, -1, NULL };
+struct td td_null_input = { NULL, 10, "", 10, 10, 100, -1, "" };
+struct td td_null_salt = { "", 10, NULL, 10, 10, 100, -1, "" };
+
+static void
+test_pkcs5_pbkdf2(gconstpointer user_data)
+{
+       struct td *data = (struct td *)user_data;
+       guchar *kd = g_malloc0(data->length);
+       gint ret;
+
+       if (data->rounds > 10000 && !g_test_slow()) {
+               gchar *msg = "Time-intensive test, rerun in slow mode to run it.";
+               g_test_skip(msg);
+               g_test_message(msg);
+               return;
+       }
+
+       if (g_test_verbose()) {
+               g_printerr("input '%s' (%ld)\nsalt '%s' (%ld)\nlength %ld\nrounds %d\nexpected_return %d\n",
+                               data->input, data->input_length,
+                               data->salt, data->salt_length,
+                               data->length,
+                               data->rounds,
+                               data->expected_return);
+       }
+
+       ret = pkcs5_pbkdf2(
+                       data->input,
+                       data->input_length,
+                       data->salt,
+                       data->salt_length,
+                       kd,
+                       data->length,
+                       data->rounds);
+
+       g_assert_cmpint(ret, ==, data->expected_return);
+       g_assert_cmpstr(kd, ==, data->expected_output);
+}
+
+static void
+test_pkcs5_pbkdf2_null_output_buffer(void)
+{
+       gint ret = pkcs5_pbkdf2("abc", 3, "abc", 3, NULL, 10, 1);
+
+       g_assert_cmpint(ret, ==, -1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       g_test_init(&argc, &argv, NULL);
+
+       g_test_add_data_func("/common/pkcs5_pbkdf2/zero_rounds",
+                       &td_zero_rounds, test_pkcs5_pbkdf2);
+       g_test_add_data_func("/common/pkcs5_pbkdf2/zero_output_length",
+                       &td_zero_output_length, test_pkcs5_pbkdf2);
+       g_test_add_data_func("/common/pkcs5_pbkdf2/null_salt",
+                       &td_null_salt, test_pkcs5_pbkdf2);
+       g_test_add_data_func("/common/pkcs5_pbkdf2/null_input",
+                       &td_null_input, test_pkcs5_pbkdf2);
+       g_test_add_func("/common/pkcs5_pbkdf2/null_output_buffer",
+                       test_pkcs5_pbkdf2_null_output_buffer);
+
+       g_test_add_data_func("/common/pkcs5_pbkdf2/rfc6070_1",
+                       &td_rfc6070_1, test_pkcs5_pbkdf2);
+       g_test_add_data_func("/common/pkcs5_pbkdf2/rfc6070_2",
+                       &td_rfc6070_2, test_pkcs5_pbkdf2);
+       g_test_add_data_func("/common/pkcs5_pbkdf2/rfc6070_3",
+                       &td_rfc6070_3, test_pkcs5_pbkdf2);
+       g_test_add_data_func("/common/pkcs5_pbkdf2/rfc6070_4",
+                       &td_rfc6070_4, test_pkcs5_pbkdf2);
+       g_test_add_data_func("/common/pkcs5_pbkdf2/rfc6070_5",
+                       &td_rfc6070_5, test_pkcs5_pbkdf2);
+       g_test_add_data_func("/common/pkcs5_pbkdf2/rfc6070_6",
+                       &td_rfc6070_6, test_pkcs5_pbkdf2);
+
+       return g_test_run();
+}
diff --git a/src/common/tests/xml_test.c b/src/common/tests/xml_test.c
new file mode 100644 (file)
index 0000000..1e58d8d
--- /dev/null
@@ -0,0 +1,39 @@
+#include <glib.h>
+
+#include "xml.h"
+
+#include "mock_prefs_common_get_use_shred.h"
+
+#define DATADIR "data/"
+
+static void
+test_xml_open_file_missing(void)
+{
+       XMLFile *xf = xml_open_file(DATADIR "missing.xml");
+       g_assert_null(xf);
+}
+
+static void
+test_xml_open_file_empty(void)
+{
+       XMLFile *xf = xml_open_file(DATADIR "empty.xml");
+       g_assert_nonnull(xf);
+       g_assert_nonnull(xf->buf);
+       g_assert_nonnull(xf->bufp);
+       g_assert_null(xf->dtd);
+       g_assert_null(xf->encoding);
+       g_assert_null(xf->tag_stack);
+       g_assert_cmpint(xf->level, ==, 0);
+       g_assert_false(xf->is_empty_element);
+}
+
+int
+main(int argc, char *argv[])
+{
+       g_test_init(&argc, &argv, NULL);
+
+       g_test_add_func("/common/xml_open_file_missing", test_xml_open_file_missing);
+       g_test_add_func("/common/xml_open_file_empty", test_xml_open_file_empty);
+
+       return g_test_run();
+}
index 111d8d1..2a6e093 100644 (file)
@@ -35,3 +35,5 @@ libclawsetpan_la_LIBADD = \
        $(GTK_LIBS) \
        $(LIBETPAN_LIBS) \
        $(ENCHANT_LIBS)
+
+.PHONY: test
index a2bcae0..633ce8a 100644 (file)
@@ -108,3 +108,5 @@ claws-marshal.h: claws-marshal.list
 
 claws-marshal.c: claws-marshal.list
        $(GLIB_GENMARSHAL) $< --body --prefix=claws_marshal > $@
+
+.PHONY: test
index 28abfdb..1f88956 100644 (file)
@@ -3,6 +3,8 @@
 # terms of the General Public License version 3 (or later).
 # See COPYING file for license details.
 
+include $(top_srcdir)/tests.mk
+
 SUBDIRS = \
        acpi_notifier \
        address_keeper \
@@ -34,3 +36,5 @@ SUBDIRS = \
        spam_report \
        tnef_parse \
        vcalendar
+
+.PHONY: test
index 2ae194c..cc794db 100644 (file)
@@ -26,3 +26,5 @@ acpi_notifier_la_CPPFLAGS = \
        -I$(top_srcdir)/src/gtk \
        $(GLIB_CFLAGS) \
        $(GTK_CFLAGS)
+
+.PHONY: test
index 4a49ae1..2388f77 100644 (file)
@@ -78,3 +78,5 @@ address_keeper_la_SOURCES = \
        address_keeper.c address_keeper.h \
        address_keeper_prefs.c address_keeper_prefs.h
 
+
+.PHONY: test
index c3cb051..5ca136d 100644 (file)
@@ -36,3 +36,5 @@ archive_la_CPPFLAGS = \
        $(GTK_CFLAGS) \
        $(ENCHANT_CFLAGS) \
        $(LIBARCHIVE_CFLAGS)
+
+.PHONY: test
index 543b5bc..a0f8b92 100644 (file)
@@ -76,3 +76,5 @@ att_remover_la_CPPFLAGS = \
        $(GLIB_CFLAGS) \
        $(GTK_CFLAGS) \
        $(ENCHANT_CFLAGS)
+
+.PHONY: test
index 146180b..6315e91 100644 (file)
@@ -78,3 +78,5 @@ attachwarner_la_SOURCES = \
        attachwarner.c attachwarner.h \
        attachwarner_prefs.c attachwarner_prefs.h
 
+
+.PHONY: test
index acb5f4e..b8b6cdc 100644 (file)
@@ -32,3 +32,5 @@ bogofilter_la_CPPFLAGS = \
        $(ENCHANT_CFLAGS) \
        $(GLIB_CFLAGS) \
        $(GTK_CFLAGS)
+
+.PHONY: test
index 72bee25..8b5d70b 100644 (file)
@@ -78,3 +78,5 @@ bsfilter_la_SOURCES = \
        bsfilter.c bsfilter.h \
        bsfilter_gtk.c
 
+
+.PHONY: test
index a66e992..2e29e49 100644 (file)
@@ -32,3 +32,5 @@ clamd_la_CPPFLAGS = \
        $(GLIB_CFLAGS) \
        $(GTK_CFLAGS) \
        $(ENCHANT_CFLAGS)
+
+.PHONY: test
index a71ac3e..12adb34 100644 (file)
@@ -26,3 +26,5 @@ noinst_HEADERS = clamd-plugin.h
 libclamd_plugin_la_LIBADD = \
        @GLIB_LIBS@ \
        @GTK_LIBS@
+
+.PHONY: test
index 8c2d43a..7593ceb 100644 (file)
@@ -29,3 +29,5 @@ demo_la_CPPFLAGS = \
        -I$(top_builddir)/src/common \
        -I$(top_srcdir)/src/common \
        $(GLIB_CFLAGS)
+
+.PHONY: test
index 5c15449..9be3c1f 100644 (file)
@@ -34,3 +34,5 @@ dillo_la_CPPFLAGS = \
        $(GLIB_CFLAGS) \
        $(GTK_CFLAGS) \
        $(ENCHANT_CFLAGS)
+
+.PHONY: test
index bfd1dd0..d436861 100644 (file)
@@ -85,3 +85,5 @@ fancy_la_CPPFLAGS = \
        $(WEBKIT_CFLAGS) \
        $(LIBSOUP_GNOME_CFLAGS) \
        $(CURL_CFLAGS)
+
+.PHONY: test
index ca84f48..338fe0a 100644 (file)
@@ -76,3 +76,5 @@ fetchinfo_la_CPPFLAGS = \
        $(GTK_CFLAGS)
 
 EXTRA_DIST = claws.def plugin.def version.rc
+
+.PHONY: test
index 84ba0ee..39db98c 100644 (file)
@@ -31,3 +31,5 @@ gdata_la_CPPFLAGS = \
        $(GTK_CFLAGS) \
        $(ENCHANT_CFLAGS) \
        $(GDATA_CFLAGS)
+
+.PHONY: test
index ac0f35c..c494b03 100644 (file)
@@ -84,3 +84,5 @@ libravatar_la_SOURCES = \
        libravatar_missing.c libravatar_missing.h \
        libravatar_federation.c libravatar_federation.h
 
+
+.PHONY: test
index 1eceab5..dffee3a 100644 (file)
@@ -88,3 +88,5 @@ mailmbox_la_CPPFLAGS = \
        $(GLIB_CFLAGS) \
        $(GTK_CFLAGS) \
        $(ENCHANT_CFLAGS)
+
+.PHONY: test
index 8a9da5d..fe4cb7d 100644 (file)
@@ -83,3 +83,5 @@ managesieve_la_SOURCES = \
        sieve_manager.c sieve_manager.h \
        sieve_editor.c sieve_editor.h
 
+
+.PHONY: test
index 286d0b1..33801fb 100644 (file)
@@ -22,3 +22,5 @@ newmail_la_CPPFLAGS = \
        -I$(top_srcdir)/src/gtk \
         $(GLIB_CFLAGS) \
        $(GTK_CFLAGS)
+
+.PHONY: test
index 35c2f1c..9d29d32 100644 (file)
@@ -109,3 +109,5 @@ notification_la_CPPFLAGS = \
 
 clean-local:
        rm -f libclaws.a
+
+.PHONY: test
index 96181d1..3975852 100644 (file)
@@ -31,3 +31,5 @@ libcmnpgtkhotkey_la_CPPFLAGS = \
        $(GLIB_CFLAGS) \
        $(GTK_CFLAGS) \
        $(CM_NP_HOTKEY_CFLAGS)
+
+.PHONY: test
index 25cabc5..c790e94 100644 (file)
@@ -27,3 +27,5 @@ pdf_viewer_la_CPPFLAGS = \
        $(GTK_CFLAGS) \
        $(ENCHANT_CFLAGS) \
        $(POPPLER_CFLAGS)
+
+.PHONY: test
index 3df58c3..1c7bca7 100644 (file)
@@ -34,3 +34,5 @@ perl_la_CPPFLAGS = \
 
 EXTRA_DIST = cm_perl.pod
 
+
+.PHONY: test
index 9744b77..65f12c0 100644 (file)
@@ -30,3 +30,5 @@ distclean-local:
        rm -f $$file; \
        done; \
        fi
+
+.PHONY: test
index 5eb32fb..c19ebcf 100644 (file)
@@ -95,3 +95,5 @@ pgpcore_la_CPPFLAGS = \
 clean-local:
        rm -f libclaws.a
 
+
+.PHONY: test
index e4ea69c..01931ea 100644 (file)
@@ -85,3 +85,5 @@ pgpinline_la_CPPFLAGS = \
 
 clean-local:
        rm -f libclaws.a
+
+.PHONY: test
index 952ce56..167894f 100644 (file)
@@ -86,3 +86,5 @@ pgpmime_la_CPPFLAGS = \
 
 clean-local:
        rm -f libclaws.a
+
+.PHONY: test
index fe7592e..36ca7c4 100644 (file)
@@ -55,3 +55,5 @@ python_la_CPPFLAGS = \
        -DPYTHON_SHARED_LIB="\"$(PYTHON_SHARED_LIB)\"" \
        -DENABLE_PYTHON \
        -fno-strict-aliasing
+
+.PHONY: test
index 5787a2c..cbd3c14 100644 (file)
@@ -13,3 +13,5 @@ EXTRA_DIST = \
        main/Open-Tomboy-Notes \
        main/Print-action-names-to-stdout \
        main/Recusively-mark-messages-as-read
+
+.PHONY: test
index 29209b2..995624c 100644 (file)
@@ -4,6 +4,10 @@
 # See COPYING file for license details.
 
 SUBDIRS = libfeed
+if BUILD_TESTS
+include $(top_srcdir)/tests.mk
+SUBDIRS += . tests
+endif
 
 EXTRA_DIST = claws.def plugin.def version.rc
 
index 456e253..4ba2a16 100644 (file)
@@ -1,5 +1,11 @@
 if BUILD_RSSYL_PLUGIN
 noinst_LTLIBRARIES = libfeed.la
+
+if BUILD_TESTS
+include $(top_srcdir)/tests.mk
+SUBDIRS = . tests
+endif
+
 endif
 
 libfeed_la_CPPFLAGS = \
diff --git a/src/plugins/rssyl/libfeed/tests/Makefile.am b/src/plugins/rssyl/libfeed/tests/Makefile.am
new file mode 100644 (file)
index 0000000..67e1f32
--- /dev/null
@@ -0,0 +1,22 @@
+include $(top_srcdir)/tests.mk
+
+common_ldadd = \
+       $(GLIB_LIBS) \
+       $(EXPAT_LIBS) \
+       $(CURL_LIBS)
+
+AM_CPPFLAGS = \
+       $(GLIB_CFLAGS) \
+       -I..
+
+TEST_PROGS += date_test
+date_test_SOURCES = date_test.c
+date_test_LDADD = $(common_ldadd) ../libfeed_la-date.o
+
+TEST_PROGS += feed_test
+feed_test_SOURCES = feed_test.c
+feed_test_LDADD = $(common_ldadd) ../libfeed.la
+
+noinst_PROGRAMS = $(TEST_PROGS)
+
+.PHONY: test
diff --git a/src/plugins/rssyl/libfeed/tests/date_test.c b/src/plugins/rssyl/libfeed/tests/date_test.c
new file mode 100644 (file)
index 0000000..cb08224
--- /dev/null
@@ -0,0 +1,34 @@
+#include <glib.h>
+
+#include "date.h"
+
+
+static void
+test_createRFC822Date (void)
+{
+       gchar *buf;
+       time_t t = 0;
+
+       buf = createRFC822Date(&t);
+       if (g_test_verbose())
+               g_printerr("time_t %ld => '%s'\n", t, buf);
+       g_assert_cmpstr(buf, ==, "Thu,  1 Jan 1970 00:00:00 GMT");
+       g_free(buf);
+
+       t = 1534240471;
+       buf = createRFC822Date(&t);
+       if (g_test_verbose())
+               g_printerr("time_t %ld => '%s'\n", t, buf);
+       g_assert_cmpstr(buf, ==, "Tue, 14 Aug 2018 09:54:31 GMT");
+       g_free(buf);
+}
+
+int
+main (int argc, char *argv[])
+{
+       g_test_init(&argc, &argv, NULL);
+
+       g_test_add_func("/rssyl/libfeed/createRFC822Date", test_createRFC822Date);
+
+       return g_test_run();
+}
diff --git a/src/plugins/rssyl/libfeed/tests/feed_test.c b/src/plugins/rssyl/libfeed/tests/feed_test.c
new file mode 100644 (file)
index 0000000..514d19a
--- /dev/null
@@ -0,0 +1,30 @@
+#include <glib.h>
+
+#include "feed.h"
+
+#include "mock_procheader_date_parse.h"
+
+#define FEED_URL "http://example.com/feed.xml"
+
+static void
+test_Feed_create(void)
+{
+       Feed *feed = feed_new(FEED_URL);
+
+       g_assert_nonnull(feed);
+       g_assert_cmpstr(feed->url, ==, FEED_URL);
+       g_assert_true(feed->is_valid);
+       g_assert_true(feed->ssl_verify_peer);
+
+       feed_free(feed);
+}
+
+int
+main(int argc, char *argv[])
+{
+       g_test_init(&argc, &argv, NULL);
+
+       g_test_add_func("/rssyl/libfeed/Feed_create", test_Feed_create);
+
+       return g_test_run();
+}
diff --git a/src/plugins/rssyl/libfeed/tests/mock_procheader_date_parse.h b/src/plugins/rssyl/libfeed/tests/mock_procheader_date_parse.h
new file mode 100644 (file)
index 0000000..37b2182
--- /dev/null
@@ -0,0 +1,7 @@
+time_t
+procheader_date_parse (gchar *dest,
+               const gchar *src,
+               gint len)
+{
+       return 1;
+}
index 2976e6f..853d118 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __STRUTILS_H
 #define __STRUTILS_H
 
+#include <glib.h>
+
 gchar *rssyl_strreplace(gchar *source, gchar *pattern,
                gchar *replacement);
 
diff --git a/src/plugins/rssyl/tests/Makefile.am b/src/plugins/rssyl/tests/Makefile.am
new file mode 100644 (file)
index 0000000..351000a
--- /dev/null
@@ -0,0 +1,17 @@
+include $(top_srcdir)/tests.mk
+
+common_ldadd = \
+       $(GLIB_LIBS)
+
+AM_CPPFLAGS = \
+       $(GLIB_CFLAGS) \
+       -I.. \
+       -I$(top_srcdir)/src
+
+TEST_PROGS += strutils_test
+strutils_test_SOURCES = strutils_test.c
+strutils_test_LDADD = $(common_ldadd) ../rssyl_la-strutils.o
+
+noinst_PROGRAMS = $(TEST_PROGS)
+
+.PHONY: test
diff --git a/src/plugins/rssyl/tests/strutils_test.c b/src/plugins/rssyl/tests/strutils_test.c
new file mode 100644 (file)
index 0000000..b3c976b
--- /dev/null
@@ -0,0 +1,53 @@
+#include "strutils.h"
+
+/* It's safe to mock this out here, we are interested in
+ * rssyl_strreplace(), which doesn't use the real function. */
+gchar *entity_decode(gchar *str)
+{
+       return g_strdup("mocked_entity_decode");
+}
+
+struct test {
+       gchar *string;
+       gchar *pattern;
+       gchar *replacement;
+       gchar *result;
+};
+
+static void
+test_strreplace(void)
+{
+       gint i;
+       static struct test strings[] = {
+               { "simplestring", "foo", "bar", "simplestring" },
+               { "foobarzot", "foo", "", "barzot" },
+               { NULL, NULL }
+       };
+
+       for (i = 0; strings[i].string != NULL; i++) {
+               gchar *result = rssyl_strreplace(
+                               strings[i].string,
+                               strings[i].pattern,
+                               strings[i].replacement);
+
+               if (g_test_verbose()) {
+                       g_printerr("string '%s', pattern '%s', replacement '%s' => result '%s'\n",
+                                       strings[i].string,
+                                       strings[i].pattern,
+                                       strings[i].replacement,
+                                       result);
+               }
+               g_assert_cmpstr(result, ==, strings[i].result);
+               g_free(result);
+       }
+}
+
+int
+main (int argc, char *argv[])
+{
+       g_test_init(&argc, &argv, NULL);
+
+       g_test_add_func("/rssyl/strreplace", test_strreplace);
+
+       return g_test_run();
+}
index c431c76..d394233 100644 (file)
@@ -87,3 +87,5 @@ smime_la_CPPFLAGS = \
 
 clean-local:
        rm -f libclaws.a
+
+.PHONY: test
index 5a077dd..e382b1f 100644 (file)
@@ -80,3 +80,5 @@ spamreport_la_CPPFLAGS = \
        $(CURL_CFLAGS) \
        $(GTK_CFLAGS) \
        $(ENCHANT_CFLAGS)
+
+.PHONY: test
index 98e3518..7e1eb2a 100644 (file)
@@ -38,3 +38,5 @@ spamassassin_la_CPPFLAGS = \
        $(SPAMASSASSIN_CFLAGS)
 
 EXTRA_DIST = README NOTICE
+
+.PHONY: test
index 3dfe9c8..2ef53a8 100644 (file)
@@ -79,3 +79,5 @@ tnef_parse_la_CPPFLAGS = \
        $(GLIB_CFLAGS) \
        $(GTK_CFLAGS) \
        $(YTNEF_CFLAGS)
+
+.PHONY: test
index c0381e7..8bceff9 100644 (file)
@@ -92,3 +92,5 @@ vcalendar_la_CPPFLAGS = \
 
 clean-local:
        rm -f libclaws.a
+
+.PHONY: test
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
new file mode 100644 (file)
index 0000000..b0a256e
--- /dev/null
@@ -0,0 +1,17 @@
+include $(top_srcdir)/tests.mk
+
+common_ldadd = \
+       $(GLIB_LIBS)
+
+AM_CPPFLAGS = \
+       $(GLIB_CFLAGS) \
+       -I$(top_srcdir)/src \
+       -I$(top_srcdir)/src/common
+
+TEST_PROGS += entity_test
+entity_test_SOURCES = entity_test.c
+entity_test_LDADD = $(common_ldadd) ../entity.o
+
+noinst_PROGRAMS = $(TEST_PROGS)
+
+.PHONY: test
diff --git a/src/tests/entity_test.c b/src/tests/entity_test.c
new file mode 100644 (file)
index 0000000..86816ea
--- /dev/null
@@ -0,0 +1,40 @@
+#include <glib.h>
+#include "mock_debug_print.h"
+
+#include "entity.h"
+
+static void
+test_entity(void)
+{
+       gchar *result;
+
+       result = entity_decode(NULL);
+       g_assert_null(result);
+
+       result = entity_decode("foo");
+       g_assert_null(result);
+
+       result = entity_decode("&Aacute;");
+       g_assert_nonnull(result);
+       if (g_test_verbose())
+               g_printerr("result '%s'\n", result);
+       g_assert_cmpstr(result, ==, "Á");
+       g_free(result);
+
+       result = entity_decode("&#123;");
+       g_assert_nonnull(result);
+       if (g_test_verbose())
+               g_printerr("result '%s'\n", result);
+       g_assert_cmpstr(result, ==, "{");
+       g_free(result);
+}
+
+int
+main(int argc, char *argv[])
+{
+       g_test_init(&argc, &argv, NULL);
+
+       g_test_add_func("/core/entity", test_entity);
+
+       return g_test_run();
+}
diff --git a/src/tests/mock_debug_print.h b/src/tests/mock_debug_print.h
new file mode 100644 (file)
index 0000000..d9e8f69
--- /dev/null
@@ -0,0 +1,2 @@
+void debug_print_real (const gchar *format, ...) { return; }
+const char *debug_srcname(const char *file) { return NULL; }
diff --git a/tests.mk b/tests.mk
new file mode 100644 (file)
index 0000000..aa5a281
--- /dev/null
+++ b/tests.mk
@@ -0,0 +1,67 @@
+GTESTER        = gtester
+GTESTER_REPORT = gtester-report
+
+# initialize variables for unconditional += appending
+TEST_PROGS =
+
+### testing rules
+
+# test: run all tests in cwd and subdirs
+test: test-cwd test-recurse
+# test-cwd: run tests in cwd
+test-cwd: ${TEST_PROGS}
+       @[ -z "$(TEST_PROGS)" ] || { set -e; $(TESTS_ENVIRONMENT) ${GTESTER} --verbose ${TEST_PROGS}; }
+
+# test-recurse: run tests in subdirs
+test-recurse:
+       @ for subdir in $(SUBDIRS) ; do \
+           test "$$subdir" = "." \
+                       -o "$$subdir" = "config" \
+                       -o "$$subdir" = "doc" \
+                       -o "$$subdir" = "manual" \
+                       -o "$$subdir" = "m4" \
+                       -o "$$subdir" = "po" \
+                       -o "$$subdir" = "tools" \
+                       || \
+           ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) test ) || exit $? ; \
+         done
+# test-report: run tests in subdirs and generate report
+# perf-report: run tests in subdirs with -m perf and generate report
+# full-report: like test-report: with -m perf and -m slow
+test-report perf-report full-report:   ${TEST_PROGS}
+       @ ignore_logdir=true ; \
+         if test -z "$$GTESTER_LOGDIR" ; then \
+           GTESTER_LOGDIR=`mktemp -d "\`pwd\`/.testlogs-XXXXXX"`; export GTESTER_LOGDIR ; \
+           ignore_logdir=false ; \
+         fi ; \
+         for subdir in $(SUBDIRS) ; do \
+           test "$$subdir" = "." -o "$$subdir" = "po" -o "$$subdir" = "po-properties" || \
+           ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \
+         done ; \
+         test -z "${TEST_PROGS}" || { \
+           case $@ in \
+           test-report) test_options="-k";; \
+           perf-report) test_options="-k -m=perf";; \
+           full-report) test_options="-k -m=perf -m=slow";; \
+           esac ; \
+           set -e; \
+           if test -z "$$GTESTER_LOGDIR" ; then \
+             ${GTESTER} --verbose $$test_options -o test-report.xml ${TEST_PROGS} ; \
+           elif test -n "${TEST_PROGS}" ; then \
+             ${GTESTER} --verbose $$test_options -o `mktemp "$$GTESTER_LOGDIR/log-XXXXXX"` ${TEST_PROGS} ; \
+           fi ; \
+         }; \
+         $$ignore_logdir || { \
+           echo '<?xml version="1.0"?>' > $@.xml ; \
+           echo '<report-collection>'  >> $@.xml ; \
+           for lf in `ls -L "$$GTESTER_LOGDIR"/.` ; do \
+             sed '1,1s/^<?xml\b[^>?]*?>//' <"$$GTESTER_LOGDIR"/"$$lf" >> $@.xml ; \
+           done ; \
+           echo >> $@.xml ; \
+           echo '</report-collection>' >> $@.xml ; \
+           rm -rf "$$GTESTER_LOGDIR"/ ; \
+           ${GTESTER_REPORT} --version 2>/dev/null 1>&2 ; test "$$?" != 0 || ${GTESTER_REPORT} $@.xml >$@.html ; \
+         }
+.PHONY: test test-cwd test-recurse test-report perf-report full-report
+# run make test-cwd as part of make check
+check-local: test-cwd
index 98d8c50..d6c9d21 100644 (file)
@@ -81,3 +81,5 @@ install-data-local:
        mkdir -p ${pkgdatadir}
        cp ${top_srcdir}/tools/ca-certificates.crt ${pkgdatadir}/
 endif
+
+.PHONY: test