[Commits] [SCM] claws branch, master, updated. 3.17.0-37-ga095dd9

ticho at claws-mail.org ticho at claws-mail.org
Fri Aug 31 14:37:52 CEST 2018


The branch, master has been updated
       via  a095dd9a48305f298d1e4621deb9aa73a2b4f08f (commit)
      from  ee945a68a8feca96d98608afc60d38272de8e385 (commit)

Summary of changes:
 .gitignore                                         |    1 +
 Makefile.am                                        |    4 +
 appdata/Makefile.am                                |    2 +
 config/Makefile.am                                 |    2 +
 config/test-driver                                 |  148 +++++++++++
 configure.ac                                       |   19 +-
 doc/Makefile.am                                    |    2 +
 doc/man/Makefile.am                                |    2 +
 m4/Makefile.am                                     |    2 +
 manual/Makefile.am                                 |    2 +
 manual/de/Makefile.am                              |    2 +
 manual/de/dist/Makefile.am                         |    2 +
 manual/de/dist/html/Makefile.am                    |    2 +
 manual/de/dist/pdf/Makefile.am                     |    2 +
 manual/de/dist/ps/Makefile.am                      |    2 +
 manual/de/dist/txt/Makefile.am                     |    2 +
 manual/dist/Makefile.am                            |    2 +
 manual/dist/html/Makefile.am                       |    2 +
 manual/dist/pdf/Makefile.am                        |    2 +
 manual/dist/ps/Makefile.am                         |    2 +
 manual/dist/txt/Makefile.am                        |    2 +
 manual/dtd/Makefile.am                             |    2 +
 manual/es/Makefile.am                              |    2 +
 manual/es/dist/Makefile.am                         |    2 +
 manual/es/dist/html/Makefile.am                    |    2 +
 manual/es/dist/pdf/Makefile.am                     |    2 +
 manual/es/dist/ps/Makefile.am                      |    2 +
 manual/es/dist/txt/Makefile.am                     |    2 +
 manual/fr/Makefile.am                              |    2 +
 manual/fr/dist/Makefile.am                         |    2 +
 manual/fr/dist/html/Makefile.am                    |    2 +
 manual/fr/dist/pdf/Makefile.am                     |    2 +
 manual/fr/dist/ps/Makefile.am                      |    2 +
 manual/fr/dist/txt/Makefile.am                     |    2 +
 manual/pl/Makefile.am                              |    2 +
 manual/pl/dist/Makefile.am                         |    2 +
 manual/pl/dist/html/Makefile.am                    |    2 +
 manual/pl/dist/pdf/Makefile.am                     |    2 +
 manual/pl/dist/ps/Makefile.am                      |    2 +
 manual/pl/dist/txt/Makefile.am                     |    2 +
 src/Makefile.am                                    |    6 +-
 src/common/Makefile.am                             |    6 +-
 src/common/tests/Makefile.am                       |   31 +++
 src/common/tests/codeconv_test.c                   |  101 ++++++++
 .../Makefile.am => src/common/tests/data/empty.xml |    0
 src/common/tests/md5_test.c                        |  256 ++++++++++++++++++++
 src/common/tests/mock_prefs_common_get_use_shred.h |    5 +
 src/common/tests/pkcs5_pbkdf2_test.c               |  121 +++++++++
 src/common/tests/xml_test.c                        |   39 +++
 src/etpan/Makefile.am                              |    2 +
 src/gtk/Makefile.am                                |    2 +
 src/plugins/Makefile.am                            |    4 +
 src/plugins/acpi_notifier/Makefile.am              |    2 +
 src/plugins/address_keeper/Makefile.am             |    2 +
 src/plugins/archive/Makefile.am                    |    2 +
 src/plugins/att_remover/Makefile.am                |    2 +
 src/plugins/attachwarner/Makefile.am               |    2 +
 src/plugins/bogofilter/Makefile.am                 |    2 +
 src/plugins/bsfilter/Makefile.am                   |    2 +
 src/plugins/clamd/Makefile.am                      |    2 +
 src/plugins/clamd/libclamd/Makefile.am             |    2 +
 src/plugins/demo/Makefile.am                       |    2 +
 src/plugins/dillo/Makefile.am                      |    2 +
 src/plugins/fancy/Makefile.am                      |    2 +
 src/plugins/fetchinfo/Makefile.am                  |    2 +
 src/plugins/gdata/Makefile.am                      |    2 +
 src/plugins/libravatar/Makefile.am                 |    2 +
 src/plugins/mailmbox/Makefile.am                   |    2 +
 src/plugins/managesieve/Makefile.am                |    2 +
 src/plugins/newmail/Makefile.am                    |    2 +
 src/plugins/notification/Makefile.am               |    2 +
 src/plugins/notification/gtkhotkey/Makefile.am     |    2 +
 src/plugins/pdf_viewer/Makefile.am                 |    2 +
 src/plugins/perl/Makefile.am                       |    2 +
 src/plugins/perl/tools/Makefile.am                 |    2 +
 src/plugins/pgpcore/Makefile.am                    |    2 +
 src/plugins/pgpinline/Makefile.am                  |    2 +
 src/plugins/pgpmime/Makefile.am                    |    2 +
 src/plugins/python/Makefile.am                     |    2 +
 src/plugins/python/examples/Makefile.am            |    2 +
 src/plugins/rssyl/Makefile.am                      |    4 +
 src/plugins/rssyl/libfeed/Makefile.am              |    6 +
 src/plugins/rssyl/libfeed/tests/Makefile.am        |   22 ++
 src/plugins/rssyl/libfeed/tests/date_test.c        |   34 +++
 src/plugins/rssyl/libfeed/tests/feed_test.c        |   30 +++
 .../libfeed/tests/mock_procheader_date_parse.h     |    7 +
 src/plugins/rssyl/strutils.h                       |    2 +
 src/plugins/rssyl/tests/Makefile.am                |   17 ++
 src/plugins/rssyl/tests/strutils_test.c            |   53 ++++
 src/plugins/smime/Makefile.am                      |    2 +
 src/plugins/spam_report/Makefile.am                |    2 +
 src/plugins/spamassassin/Makefile.am               |    2 +
 src/plugins/tnef_parse/Makefile.am                 |    2 +
 src/plugins/vcalendar/Makefile.am                  |    2 +
 src/tests/Makefile.am                              |   17 ++
 src/tests/entity_test.c                            |   40 +++
 src/tests/mock_debug_print.h                       |    2 +
 tests.mk                                           |   67 +++++
 tools/Makefile.am                                  |    2 +
 99 files changed, 1183 insertions(+), 3 deletions(-)
 create mode 100755 config/test-driver
 create mode 100644 src/common/tests/Makefile.am
 create mode 100644 src/common/tests/codeconv_test.c
 copy config/Makefile.am => src/common/tests/data/empty.xml (100%)
 create mode 100644 src/common/tests/md5_test.c
 create mode 100644 src/common/tests/mock_prefs_common_get_use_shred.h
 create mode 100644 src/common/tests/pkcs5_pbkdf2_test.c
 create mode 100644 src/common/tests/xml_test.c
 create mode 100644 src/plugins/rssyl/libfeed/tests/Makefile.am
 create mode 100644 src/plugins/rssyl/libfeed/tests/date_test.c
 create mode 100644 src/plugins/rssyl/libfeed/tests/feed_test.c
 create mode 100644 src/plugins/rssyl/libfeed/tests/mock_procheader_date_parse.h
 create mode 100644 src/plugins/rssyl/tests/Makefile.am
 create mode 100644 src/plugins/rssyl/tests/strutils_test.c
 create mode 100644 src/tests/Makefile.am
 create mode 100644 src/tests/entity_test.c
 create mode 100644 src/tests/mock_debug_print.h
 create mode 100644 tests.mk


- Log -----------------------------------------------------------------
commit a095dd9a48305f298d1e4621deb9aa73a2b4f08f
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Fri Aug 31 13:48:30 2018 +0200

    Added unit test framework, and some initial unit tests.

diff --git a/.gitignore b/.gitignore
index 0cb7868..bebe946 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/Makefile.am b/Makefile.am
index 3fdb4aa..cbbe2f2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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
 
diff --git a/appdata/Makefile.am b/appdata/Makefile.am
index 15066a2..30e47f5 100644
--- a/appdata/Makefile.am
+++ b/appdata/Makefile.am
@@ -40,3 +40,5 @@ appdata_DATA = $(appdata_in_files:.xml.in=.xml)
 
 EXTRA_DIST = $(appdata_DATA) $(appdata_in_files)
 
+
+.PHONY: test
diff --git a/config/Makefile.am b/config/Makefile.am
index e69de29..d4b3f0a 100644
--- a/config/Makefile.am
+++ b/config/Makefile.am
@@ -0,0 +1,2 @@
+
+.PHONY: test
diff --git a/config/test-driver b/config/test-driver
new file mode 100755
index 0000000..0218a01
--- /dev/null
+++ b/config/test-driver
@@ -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 at gnu.org> or send patches to
+# <automake-patches at 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='' # Red.
+  grn='' # Green.
+  lgn='' # Light green.
+  blu='' # Blue.
+  mgn='' # Magenta.
+  std=''     # 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:
diff --git a/configure.ac b/configure.ac
index edf7767..50766e1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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:"
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 5beeea0..a808617 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS = man
+
+.PHONY: test
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
index 54e06ae..c2c91a4 100644
--- a/doc/man/Makefile.am
+++ b/doc/man/Makefile.am
@@ -7,3 +7,5 @@ man_MANS = \
      claws-mail.1
 
 EXTRA_DIST = $(man_MANS)
+
+.PHONY: test
diff --git a/m4/Makefile.am b/m4/Makefile.am
index b409865..be424a8 100644
--- a/m4/Makefile.am
+++ b/m4/Makefile.am
@@ -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
diff --git a/manual/Makefile.am b/manual/Makefile.am
index 179cd66..32f2495 100644
--- a/manual/Makefile.am
+++ b/manual/Makefile.am
@@ -21,3 +21,5 @@ EXTRA_DIST = \
 	plugins.xml \
 	starting.xml \
 	claws-mail-manual.xml
+
+.PHONY: test
diff --git a/manual/de/Makefile.am b/manual/de/Makefile.am
index 00f1ca8..1a605a6 100644
--- a/manual/de/Makefile.am
+++ b/manual/de/Makefile.am
@@ -21,3 +21,5 @@ EXTRA_DIST = \
 	plugins.xml \
 	starting.xml \
 	claws-mail-manual.xml
+
+.PHONY: test
diff --git a/manual/de/dist/Makefile.am b/manual/de/dist/Makefile.am
index 9bff2bd..c19a2fd 100644
--- a/manual/de/dist/Makefile.am
+++ b/manual/de/dist/Makefile.am
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS=html pdf ps txt
+
+.PHONY: test
diff --git a/manual/de/dist/html/Makefile.am b/manual/de/dist/html/Makefile.am
index 3560fd4..9b09880 100644
--- a/manual/de/dist/html/Makefile.am
+++ b/manual/de/dist/html/Makefile.am
@@ -31,3 +31,5 @@ maintainer-clean:
 	-rm claws-mail-manual.html
 	-rm claws-mail-manual.html.raw
 endif
+
+.PHONY: test
diff --git a/manual/de/dist/pdf/Makefile.am b/manual/de/dist/pdf/Makefile.am
index 050a7d9..c5a3b9e 100644
--- a/manual/de/dist/pdf/Makefile.am
+++ b/manual/de/dist/pdf/Makefile.am
@@ -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
diff --git a/manual/de/dist/ps/Makefile.am b/manual/de/dist/ps/Makefile.am
index 96a9069..8c2ca03 100644
--- a/manual/de/dist/ps/Makefile.am
+++ b/manual/de/dist/ps/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.ps: \
 maintainer-clean:
 	-rm claws-mail-manual.ps
 endif
+
+.PHONY: test
diff --git a/manual/de/dist/txt/Makefile.am b/manual/de/dist/txt/Makefile.am
index 020fbf2..26017b6 100644
--- a/manual/de/dist/txt/Makefile.am
+++ b/manual/de/dist/txt/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.txt: \
 maintainer-clean:
 	-rm claws-mail-manual.txt
 endif
+
+.PHONY: test
diff --git a/manual/dist/Makefile.am b/manual/dist/Makefile.am
index 9bff2bd..c19a2fd 100644
--- a/manual/dist/Makefile.am
+++ b/manual/dist/Makefile.am
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS=html pdf ps txt
+
+.PHONY: test
diff --git a/manual/dist/html/Makefile.am b/manual/dist/html/Makefile.am
index 3f66e1c..cf1d577 100644
--- a/manual/dist/html/Makefile.am
+++ b/manual/dist/html/Makefile.am
@@ -31,3 +31,5 @@ maintainer-clean:
 	-rm claws-mail-manual.html
 	-rm claws-mail-manual.html.raw
 endif
+
+.PHONY: test
diff --git a/manual/dist/pdf/Makefile.am b/manual/dist/pdf/Makefile.am
index 2a78f05..10329e2 100644
--- a/manual/dist/pdf/Makefile.am
+++ b/manual/dist/pdf/Makefile.am
@@ -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
diff --git a/manual/dist/ps/Makefile.am b/manual/dist/ps/Makefile.am
index d4f067c..0c82b57 100644
--- a/manual/dist/ps/Makefile.am
+++ b/manual/dist/ps/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.ps: \
 maintainer-clean:
 	-rm claws-mail-manual.ps
 endif
+
+.PHONY: test
diff --git a/manual/dist/txt/Makefile.am b/manual/dist/txt/Makefile.am
index 34ddc40..afda992 100644
--- a/manual/dist/txt/Makefile.am
+++ b/manual/dist/txt/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.txt: \
 maintainer-clean:
 	-rm claws-mail-manual.txt
 endif
+
+.PHONY: test
diff --git a/manual/dtd/Makefile.am b/manual/dtd/Makefile.am
index 0c134f1..024b07f 100644
--- a/manual/dtd/Makefile.am
+++ b/manual/dtd/Makefile.am
@@ -5,3 +5,5 @@
 
 EXTRA_DIST= \
 	manual.dsl  sdocbook.dtd
+
+.PHONY: test
diff --git a/manual/es/Makefile.am b/manual/es/Makefile.am
index 00f1ca8..1a605a6 100644
--- a/manual/es/Makefile.am
+++ b/manual/es/Makefile.am
@@ -21,3 +21,5 @@ EXTRA_DIST = \
 	plugins.xml \
 	starting.xml \
 	claws-mail-manual.xml
+
+.PHONY: test
diff --git a/manual/es/dist/Makefile.am b/manual/es/dist/Makefile.am
index 9bff2bd..c19a2fd 100644
--- a/manual/es/dist/Makefile.am
+++ b/manual/es/dist/Makefile.am
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS=html pdf ps txt
+
+.PHONY: test
diff --git a/manual/es/dist/html/Makefile.am b/manual/es/dist/html/Makefile.am
index 155d8f9..05cec3a 100644
--- a/manual/es/dist/html/Makefile.am
+++ b/manual/es/dist/html/Makefile.am
@@ -31,3 +31,5 @@ maintainer-clean:
 	-rm claws-mail-manual.html
 	-rm claws-mail-manual.html.raw
 endif
+
+.PHONY: test
diff --git a/manual/es/dist/pdf/Makefile.am b/manual/es/dist/pdf/Makefile.am
index 4382322..ac779fb 100644
--- a/manual/es/dist/pdf/Makefile.am
+++ b/manual/es/dist/pdf/Makefile.am
@@ -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
diff --git a/manual/es/dist/ps/Makefile.am b/manual/es/dist/ps/Makefile.am
index 7b26017..fa3e936 100644
--- a/manual/es/dist/ps/Makefile.am
+++ b/manual/es/dist/ps/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.ps: \
 maintainer-clean:
 	-rm claws-mail-manual.ps
 endif
+
+.PHONY: test
diff --git a/manual/es/dist/txt/Makefile.am b/manual/es/dist/txt/Makefile.am
index d3c7b61..8ced198 100644
--- a/manual/es/dist/txt/Makefile.am
+++ b/manual/es/dist/txt/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.txt: \
 maintainer-clean:
 	-rm claws-mail-manual.txt
 endif
+
+.PHONY: test
diff --git a/manual/fr/Makefile.am b/manual/fr/Makefile.am
index 00f1ca8..1a605a6 100644
--- a/manual/fr/Makefile.am
+++ b/manual/fr/Makefile.am
@@ -21,3 +21,5 @@ EXTRA_DIST = \
 	plugins.xml \
 	starting.xml \
 	claws-mail-manual.xml
+
+.PHONY: test
diff --git a/manual/fr/dist/Makefile.am b/manual/fr/dist/Makefile.am
index 9bff2bd..c19a2fd 100644
--- a/manual/fr/dist/Makefile.am
+++ b/manual/fr/dist/Makefile.am
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS=html pdf ps txt
+
+.PHONY: test
diff --git a/manual/fr/dist/html/Makefile.am b/manual/fr/dist/html/Makefile.am
index a44d39d..0a04981 100644
--- a/manual/fr/dist/html/Makefile.am
+++ b/manual/fr/dist/html/Makefile.am
@@ -31,3 +31,5 @@ maintainer-clean:
 	-rm claws-mail-manual.html
 	-rm claws-mail-manual.html.raw
 endif
+
+.PHONY: test
diff --git a/manual/fr/dist/pdf/Makefile.am b/manual/fr/dist/pdf/Makefile.am
index b7a8a53..2c8f1c3 100644
--- a/manual/fr/dist/pdf/Makefile.am
+++ b/manual/fr/dist/pdf/Makefile.am
@@ -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
diff --git a/manual/fr/dist/ps/Makefile.am b/manual/fr/dist/ps/Makefile.am
index 53f5bdb..bb9a6da 100644
--- a/manual/fr/dist/ps/Makefile.am
+++ b/manual/fr/dist/ps/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.ps: \
 maintainer-clean:
 	-rm claws-mail-manual.ps
 endif
+
+.PHONY: test
diff --git a/manual/fr/dist/txt/Makefile.am b/manual/fr/dist/txt/Makefile.am
index 957b1bf..1647679 100644
--- a/manual/fr/dist/txt/Makefile.am
+++ b/manual/fr/dist/txt/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.txt: \
 maintainer-clean:
 	-rm claws-mail-manual.txt
 endif
+
+.PHONY: test
diff --git a/manual/pl/Makefile.am b/manual/pl/Makefile.am
index 00f1ca8..1a605a6 100644
--- a/manual/pl/Makefile.am
+++ b/manual/pl/Makefile.am
@@ -21,3 +21,5 @@ EXTRA_DIST = \
 	plugins.xml \
 	starting.xml \
 	claws-mail-manual.xml
+
+.PHONY: test
diff --git a/manual/pl/dist/Makefile.am b/manual/pl/dist/Makefile.am
index 9bff2bd..c19a2fd 100644
--- a/manual/pl/dist/Makefile.am
+++ b/manual/pl/dist/Makefile.am
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS=html pdf ps txt
+
+.PHONY: test
diff --git a/manual/pl/dist/html/Makefile.am b/manual/pl/dist/html/Makefile.am
index c1f3ef6..680e4a4 100644
--- a/manual/pl/dist/html/Makefile.am
+++ b/manual/pl/dist/html/Makefile.am
@@ -31,3 +31,5 @@ maintainer-clean:
 	-rm claws-mail-manual.html
 	-rm claws-mail-manual.html.raw
 endif
+
+.PHONY: test
diff --git a/manual/pl/dist/pdf/Makefile.am b/manual/pl/dist/pdf/Makefile.am
index 02eec0b..a599ace 100644
--- a/manual/pl/dist/pdf/Makefile.am
+++ b/manual/pl/dist/pdf/Makefile.am
@@ -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
diff --git a/manual/pl/dist/ps/Makefile.am b/manual/pl/dist/ps/Makefile.am
index 48a27df..64ad9c0 100644
--- a/manual/pl/dist/ps/Makefile.am
+++ b/manual/pl/dist/ps/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.ps: \
 maintainer-clean:
 	-rm claws-mail-manual.ps
 endif
+
+.PHONY: test
diff --git a/manual/pl/dist/txt/Makefile.am b/manual/pl/dist/txt/Makefile.am
index 31c051d..17f970f 100644
--- a/manual/pl/dist/txt/Makefile.am
+++ b/manual/pl/dist/txt/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.txt: \
 maintainer-clean:
 	-rm claws-mail-manual.txt
 endif
+
+.PHONY: test
diff --git a/src/Makefile.am b/src/Makefile.am
index 30e85a4..9844f30 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -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:
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 56b6cdb..5c4f249 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -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
index 0000000..7b18f88
--- /dev/null
+++ b/src/common/tests/Makefile.am
@@ -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
index 0000000..3b93eae
--- /dev/null
+++ b/src/common/tests/codeconv_test.c
@@ -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/config/Makefile.am b/src/common/tests/data/empty.xml
similarity index 100%
copy from config/Makefile.am
copy to src/common/tests/data/empty.xml
diff --git a/src/common/tests/md5_test.c b/src/common/tests/md5_test.c
new file mode 100644
index 0000000..e78d118
--- /dev/null
+++ b/src/common/tests/md5_test.c
@@ -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
index 0000000..a216cbd
--- /dev/null
+++ b/src/common/tests/mock_prefs_common_get_use_shred.h
@@ -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
index 0000000..3f7a451
--- /dev/null
+++ b/src/common/tests/pkcs5_pbkdf2_test.c
@@ -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
index 0000000..1e58d8d
--- /dev/null
+++ b/src/common/tests/xml_test.c
@@ -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();
+}
diff --git a/src/etpan/Makefile.am b/src/etpan/Makefile.am
index 111d8d1..2a6e093 100644
--- a/src/etpan/Makefile.am
+++ b/src/etpan/Makefile.am
@@ -35,3 +35,5 @@ libclawsetpan_la_LIBADD = \
 	$(GTK_LIBS) \
 	$(LIBETPAN_LIBS) \
 	$(ENCHANT_LIBS)
+
+.PHONY: test
diff --git a/src/gtk/Makefile.am b/src/gtk/Makefile.am
index a2bcae0..633ce8a 100644
--- a/src/gtk/Makefile.am
+++ b/src/gtk/Makefile.am
@@ -108,3 +108,5 @@ claws-marshal.h: claws-marshal.list
 
 claws-marshal.c: claws-marshal.list
 	$(GLIB_GENMARSHAL) $< --body --prefix=claws_marshal > $@
+
+.PHONY: test
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 28abfdb..1f88956 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -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
diff --git a/src/plugins/acpi_notifier/Makefile.am b/src/plugins/acpi_notifier/Makefile.am
index 2ae194c..cc794db 100644
--- a/src/plugins/acpi_notifier/Makefile.am
+++ b/src/plugins/acpi_notifier/Makefile.am
@@ -26,3 +26,5 @@ acpi_notifier_la_CPPFLAGS = \
 	-I$(top_srcdir)/src/gtk \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/address_keeper/Makefile.am b/src/plugins/address_keeper/Makefile.am
index 4a49ae1..2388f77 100644
--- a/src/plugins/address_keeper/Makefile.am
+++ b/src/plugins/address_keeper/Makefile.am
@@ -78,3 +78,5 @@ address_keeper_la_SOURCES = \
 	address_keeper.c address_keeper.h \
 	address_keeper_prefs.c address_keeper_prefs.h
 
+
+.PHONY: test
diff --git a/src/plugins/archive/Makefile.am b/src/plugins/archive/Makefile.am
index c3cb051..5ca136d 100644
--- a/src/plugins/archive/Makefile.am
+++ b/src/plugins/archive/Makefile.am
@@ -36,3 +36,5 @@ archive_la_CPPFLAGS = \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS) \
 	$(LIBARCHIVE_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/att_remover/Makefile.am b/src/plugins/att_remover/Makefile.am
index 543b5bc..a0f8b92 100644
--- a/src/plugins/att_remover/Makefile.am
+++ b/src/plugins/att_remover/Makefile.am
@@ -76,3 +76,5 @@ att_remover_la_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/attachwarner/Makefile.am b/src/plugins/attachwarner/Makefile.am
index 146180b..6315e91 100644
--- a/src/plugins/attachwarner/Makefile.am
+++ b/src/plugins/attachwarner/Makefile.am
@@ -78,3 +78,5 @@ attachwarner_la_SOURCES = \
 	attachwarner.c attachwarner.h \
 	attachwarner_prefs.c attachwarner_prefs.h
 
+
+.PHONY: test
diff --git a/src/plugins/bogofilter/Makefile.am b/src/plugins/bogofilter/Makefile.am
index acb5f4e..b8b6cdc 100644
--- a/src/plugins/bogofilter/Makefile.am
+++ b/src/plugins/bogofilter/Makefile.am
@@ -32,3 +32,5 @@ bogofilter_la_CPPFLAGS = \
 	$(ENCHANT_CFLAGS) \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/bsfilter/Makefile.am b/src/plugins/bsfilter/Makefile.am
index 72bee25..8b5d70b 100644
--- a/src/plugins/bsfilter/Makefile.am
+++ b/src/plugins/bsfilter/Makefile.am
@@ -78,3 +78,5 @@ bsfilter_la_SOURCES = \
 	bsfilter.c bsfilter.h \
 	bsfilter_gtk.c
 
+
+.PHONY: test
diff --git a/src/plugins/clamd/Makefile.am b/src/plugins/clamd/Makefile.am
index a66e992..2e29e49 100644
--- a/src/plugins/clamd/Makefile.am
+++ b/src/plugins/clamd/Makefile.am
@@ -32,3 +32,5 @@ clamd_la_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/clamd/libclamd/Makefile.am b/src/plugins/clamd/libclamd/Makefile.am
index a71ac3e..12adb34 100644
--- a/src/plugins/clamd/libclamd/Makefile.am
+++ b/src/plugins/clamd/libclamd/Makefile.am
@@ -26,3 +26,5 @@ noinst_HEADERS = clamd-plugin.h
 libclamd_plugin_la_LIBADD = \
 	@GLIB_LIBS@ \
 	@GTK_LIBS@
+
+.PHONY: test
diff --git a/src/plugins/demo/Makefile.am b/src/plugins/demo/Makefile.am
index 8c2d43a..7593ceb 100644
--- a/src/plugins/demo/Makefile.am
+++ b/src/plugins/demo/Makefile.am
@@ -29,3 +29,5 @@ demo_la_CPPFLAGS = \
 	-I$(top_builddir)/src/common \
 	-I$(top_srcdir)/src/common \
 	$(GLIB_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/dillo/Makefile.am b/src/plugins/dillo/Makefile.am
index 5c15449..9be3c1f 100644
--- a/src/plugins/dillo/Makefile.am
+++ b/src/plugins/dillo/Makefile.am
@@ -34,3 +34,5 @@ dillo_la_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/fancy/Makefile.am b/src/plugins/fancy/Makefile.am
index bfd1dd0..d436861 100644
--- a/src/plugins/fancy/Makefile.am
+++ b/src/plugins/fancy/Makefile.am
@@ -85,3 +85,5 @@ fancy_la_CPPFLAGS = \
 	$(WEBKIT_CFLAGS) \
 	$(LIBSOUP_GNOME_CFLAGS) \
 	$(CURL_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/fetchinfo/Makefile.am b/src/plugins/fetchinfo/Makefile.am
index ca84f48..338fe0a 100644
--- a/src/plugins/fetchinfo/Makefile.am
+++ b/src/plugins/fetchinfo/Makefile.am
@@ -76,3 +76,5 @@ fetchinfo_la_CPPFLAGS = \
 	$(GTK_CFLAGS)
 
 EXTRA_DIST = claws.def plugin.def version.rc
+
+.PHONY: test
diff --git a/src/plugins/gdata/Makefile.am b/src/plugins/gdata/Makefile.am
index 84ba0ee..39db98c 100644
--- a/src/plugins/gdata/Makefile.am
+++ b/src/plugins/gdata/Makefile.am
@@ -31,3 +31,5 @@ gdata_la_CPPFLAGS = \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS) \
 	$(GDATA_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/libravatar/Makefile.am b/src/plugins/libravatar/Makefile.am
index ac0f35c..c494b03 100644
--- a/src/plugins/libravatar/Makefile.am
+++ b/src/plugins/libravatar/Makefile.am
@@ -84,3 +84,5 @@ libravatar_la_SOURCES = \
 	libravatar_missing.c libravatar_missing.h \
 	libravatar_federation.c libravatar_federation.h
 
+
+.PHONY: test
diff --git a/src/plugins/mailmbox/Makefile.am b/src/plugins/mailmbox/Makefile.am
index 1eceab5..dffee3a 100644
--- a/src/plugins/mailmbox/Makefile.am
+++ b/src/plugins/mailmbox/Makefile.am
@@ -88,3 +88,5 @@ mailmbox_la_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/managesieve/Makefile.am b/src/plugins/managesieve/Makefile.am
index 8a9da5d..fe4cb7d 100644
--- a/src/plugins/managesieve/Makefile.am
+++ b/src/plugins/managesieve/Makefile.am
@@ -83,3 +83,5 @@ managesieve_la_SOURCES = \
 	sieve_manager.c sieve_manager.h \
 	sieve_editor.c sieve_editor.h
 
+
+.PHONY: test
diff --git a/src/plugins/newmail/Makefile.am b/src/plugins/newmail/Makefile.am
index 286d0b1..33801fb 100644
--- a/src/plugins/newmail/Makefile.am
+++ b/src/plugins/newmail/Makefile.am
@@ -22,3 +22,5 @@ newmail_la_CPPFLAGS = \
 	-I$(top_srcdir)/src/gtk \
         $(GLIB_CFLAGS) \
 	$(GTK_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/notification/Makefile.am b/src/plugins/notification/Makefile.am
index 35c2f1c..9d29d32 100644
--- a/src/plugins/notification/Makefile.am
+++ b/src/plugins/notification/Makefile.am
@@ -109,3 +109,5 @@ notification_la_CPPFLAGS = \
 
 clean-local:
 	rm -f libclaws.a
+
+.PHONY: test
diff --git a/src/plugins/notification/gtkhotkey/Makefile.am b/src/plugins/notification/gtkhotkey/Makefile.am
index 96181d1..3975852 100644
--- a/src/plugins/notification/gtkhotkey/Makefile.am
+++ b/src/plugins/notification/gtkhotkey/Makefile.am
@@ -31,3 +31,5 @@ libcmnpgtkhotkey_la_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(CM_NP_HOTKEY_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/pdf_viewer/Makefile.am b/src/plugins/pdf_viewer/Makefile.am
index 25cabc5..c790e94 100644
--- a/src/plugins/pdf_viewer/Makefile.am
+++ b/src/plugins/pdf_viewer/Makefile.am
@@ -27,3 +27,5 @@ pdf_viewer_la_CPPFLAGS = \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS) \
 	$(POPPLER_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/perl/Makefile.am b/src/plugins/perl/Makefile.am
index 3df58c3..1c7bca7 100644
--- a/src/plugins/perl/Makefile.am
+++ b/src/plugins/perl/Makefile.am
@@ -34,3 +34,5 @@ perl_la_CPPFLAGS = \
 
 EXTRA_DIST = cm_perl.pod
 
+
+.PHONY: test
diff --git a/src/plugins/perl/tools/Makefile.am b/src/plugins/perl/tools/Makefile.am
index 9744b77..65f12c0 100644
--- a/src/plugins/perl/tools/Makefile.am
+++ b/src/plugins/perl/tools/Makefile.am
@@ -30,3 +30,5 @@ distclean-local:
 	rm -f $$file; \
 	done; \
 	fi
+
+.PHONY: test
diff --git a/src/plugins/pgpcore/Makefile.am b/src/plugins/pgpcore/Makefile.am
index 5eb32fb..c19ebcf 100644
--- a/src/plugins/pgpcore/Makefile.am
+++ b/src/plugins/pgpcore/Makefile.am
@@ -95,3 +95,5 @@ pgpcore_la_CPPFLAGS = \
 clean-local:
 	rm -f libclaws.a
 
+
+.PHONY: test
diff --git a/src/plugins/pgpinline/Makefile.am b/src/plugins/pgpinline/Makefile.am
index e4ea69c..01931ea 100644
--- a/src/plugins/pgpinline/Makefile.am
+++ b/src/plugins/pgpinline/Makefile.am
@@ -85,3 +85,5 @@ pgpinline_la_CPPFLAGS = \
 
 clean-local:
 	rm -f libclaws.a
+
+.PHONY: test
diff --git a/src/plugins/pgpmime/Makefile.am b/src/plugins/pgpmime/Makefile.am
index 952ce56..167894f 100644
--- a/src/plugins/pgpmime/Makefile.am
+++ b/src/plugins/pgpmime/Makefile.am
@@ -86,3 +86,5 @@ pgpmime_la_CPPFLAGS = \
 
 clean-local:
 	rm -f libclaws.a
+
+.PHONY: test
diff --git a/src/plugins/python/Makefile.am b/src/plugins/python/Makefile.am
index fe7592e..36ca7c4 100644
--- a/src/plugins/python/Makefile.am
+++ b/src/plugins/python/Makefile.am
@@ -55,3 +55,5 @@ python_la_CPPFLAGS = \
 	-DPYTHON_SHARED_LIB="\"$(PYTHON_SHARED_LIB)\"" \
 	-DENABLE_PYTHON \
 	-fno-strict-aliasing
+
+.PHONY: test
diff --git a/src/plugins/python/examples/Makefile.am b/src/plugins/python/examples/Makefile.am
index 5787a2c..cbd3c14 100644
--- a/src/plugins/python/examples/Makefile.am
+++ b/src/plugins/python/examples/Makefile.am
@@ -13,3 +13,5 @@ EXTRA_DIST = \
 	main/Open-Tomboy-Notes \
 	main/Print-action-names-to-stdout \
 	main/Recusively-mark-messages-as-read
+
+.PHONY: test
diff --git a/src/plugins/rssyl/Makefile.am b/src/plugins/rssyl/Makefile.am
index 29209b2..995624c 100644
--- a/src/plugins/rssyl/Makefile.am
+++ b/src/plugins/rssyl/Makefile.am
@@ -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
 
diff --git a/src/plugins/rssyl/libfeed/Makefile.am b/src/plugins/rssyl/libfeed/Makefile.am
index 456e253..4ba2a16 100644
--- a/src/plugins/rssyl/libfeed/Makefile.am
+++ b/src/plugins/rssyl/libfeed/Makefile.am
@@ -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
index 0000000..67e1f32
--- /dev/null
+++ b/src/plugins/rssyl/libfeed/tests/Makefile.am
@@ -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
index 0000000..cb08224
--- /dev/null
+++ b/src/plugins/rssyl/libfeed/tests/date_test.c
@@ -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
index 0000000..514d19a
--- /dev/null
+++ b/src/plugins/rssyl/libfeed/tests/feed_test.c
@@ -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
index 0000000..37b2182
--- /dev/null
+++ b/src/plugins/rssyl/libfeed/tests/mock_procheader_date_parse.h
@@ -0,0 +1,7 @@
+time_t
+procheader_date_parse (gchar *dest,
+		const gchar *src,
+		gint len)
+{
+	return 1;
+}
diff --git a/src/plugins/rssyl/strutils.h b/src/plugins/rssyl/strutils.h
index 2976e6f..853d118 100644
--- a/src/plugins/rssyl/strutils.h
+++ b/src/plugins/rssyl/strutils.h
@@ -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
index 0000000..351000a
--- /dev/null
+++ b/src/plugins/rssyl/tests/Makefile.am
@@ -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
index 0000000..b3c976b
--- /dev/null
+++ b/src/plugins/rssyl/tests/strutils_test.c
@@ -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();
+}
diff --git a/src/plugins/smime/Makefile.am b/src/plugins/smime/Makefile.am
index c431c76..d394233 100644
--- a/src/plugins/smime/Makefile.am
+++ b/src/plugins/smime/Makefile.am
@@ -87,3 +87,5 @@ smime_la_CPPFLAGS = \
 
 clean-local:
 	rm -f libclaws.a
+
+.PHONY: test
diff --git a/src/plugins/spam_report/Makefile.am b/src/plugins/spam_report/Makefile.am
index 5a077dd..e382b1f 100644
--- a/src/plugins/spam_report/Makefile.am
+++ b/src/plugins/spam_report/Makefile.am
@@ -80,3 +80,5 @@ spamreport_la_CPPFLAGS = \
 	$(CURL_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/spamassassin/Makefile.am b/src/plugins/spamassassin/Makefile.am
index 98e3518..7e1eb2a 100644
--- a/src/plugins/spamassassin/Makefile.am
+++ b/src/plugins/spamassassin/Makefile.am
@@ -38,3 +38,5 @@ spamassassin_la_CPPFLAGS = \
 	$(SPAMASSASSIN_CFLAGS)
 
 EXTRA_DIST = README NOTICE
+
+.PHONY: test
diff --git a/src/plugins/tnef_parse/Makefile.am b/src/plugins/tnef_parse/Makefile.am
index 3dfe9c8..2ef53a8 100644
--- a/src/plugins/tnef_parse/Makefile.am
+++ b/src/plugins/tnef_parse/Makefile.am
@@ -79,3 +79,5 @@ tnef_parse_la_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(YTNEF_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/vcalendar/Makefile.am b/src/plugins/vcalendar/Makefile.am
index c0381e7..8bceff9 100644
--- a/src/plugins/vcalendar/Makefile.am
+++ b/src/plugins/vcalendar/Makefile.am
@@ -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
index 0000000..b0a256e
--- /dev/null
+++ b/src/tests/Makefile.am
@@ -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
index 0000000..86816ea
--- /dev/null
+++ b/src/tests/entity_test.c
@@ -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("Á");
+	g_assert_nonnull(result);
+	if (g_test_verbose())
+		g_printerr("result '%s'\n", result);
+	g_assert_cmpstr(result, ==, "Á");
+	g_free(result);
+
+	result = entity_decode("{");
+	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
index 0000000..d9e8f69
--- /dev/null
+++ b/src/tests/mock_debug_print.h
@@ -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
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
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 98d8c50..d6c9d21 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -81,3 +81,5 @@ install-data-local:
 	mkdir -p ${pkgdatadir}
 	cp ${top_srcdir}/tools/ca-certificates.crt ${pkgdatadir}/
 endif
+
+.PHONY: test

-----------------------------------------------------------------------


hooks/post-receive
-- 
Claws Mail


More information about the Commits mailing list