Techniques to detect API/ABI changes



2006/11/25, Philip Van Hoof <spam pvanhoof be>:
On Fri, 2006-11-24 at 21:36 +0100, Øystein Gisnås wrote:
> 2006/11/13, Philip Van Hoof <spam pvanhoof be>:

> My idea is to put together a special suite of unit tests for testing
> the API. It should only test what's exposed through the library
> headers. I also think it should test against the libraries installed
> on the system, that is using .pc files to resolve flags. That way we
> can test against the installed version. During development, breakage
> will show in the normal unit tests. When it's time for release we can
> test the new codebase against the previous released version and in
> theory get a list of broken APIs.
>
> I hacked together a Makefile in a directory parallel to
> libtinymail-test/, and it was quite simple to get things going..

Ok. Go ahead and show me your experiments early so that I can tell you
what I would and what I wouldn't like early too :)

I left it in the same directory as libtinymail-test (less clutter),
added a configure flag. It's basically a new GUnit suite testing only
public interfaces and not pulling libraries from current build.
Index: libtinymail-test/tny-api-test-suite.c
===================================================================
--- libtinymail-test/tny-api-test-suite.c	(revisjon 0)
+++ libtinymail-test/tny-api-test-suite.c	(revisjon 0)
@@ -0,0 +1,49 @@
+/* tinymail - Tinymail GUnit API test suite
+ * Copyright (C) 2006 �ystein Gisnås <oystein gisnas net>
+ * Based on tny-test-suite.c which is
+ * Copyright (C) 2006-2007 Philip Van Hoof <pvanhoof gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with self program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+/* Usage:
+ * export LD_LIBRARY_PATH=./libtinymail-test/.libs/
+ * gunit-test-runner-tool -s tinymail-api-test-suite -v gnome
+ */
+
+#include "tny-test-suite.h"
+
+#include "tny-simple-list-test.h"
+
+GList*
+gunit_get_test_suites()
+{
+	GList *suites = NULL;
+
+	suites = g_list_append (suites, create_tny_list_suite ());
+	suites = g_list_append (suites, create_tny_device_suite ());
+	suites = g_list_append (suites, create_tny_account_suite ());
+	suites = g_list_append (suites, create_tny_folder_suite ());
+	suites = g_list_append (suites, create_tny_mime_part_suite ());
+/* 	suites = g_list_append (suites, create_tny_stream_suite ()); */
+	suites = g_list_append (suites, create_tny_header_suite ());
+	suites = g_list_append (suites, create_tny_folder_store_query_suite ());
+/* 	suites = g_list_append (suites, create_tny_msg_suite ()); */
+	suites = g_list_append (suites, create_tny_account_store_suite ());
+	suites = g_list_append (suites, create_tny_platform_factory_suite ());
+    
+	return suites;
+}
Index: libtinymail-test/tny-simple-api-test-runner.c
===================================================================
--- libtinymail-test/tny-simple-api-test-runner.c	(revisjon 0)
+++ libtinymail-test/tny-simple-api-test-runner.c	(revisjon 0)
@@ -0,0 +1,175 @@
+#include "tny-test-suite.h" 
+#include <view.h>
+
+static GObjectClass *parent_class = NULL;
+
+typedef struct _TnyTestView TnyTestView;
+typedef struct _TnyTestViewClass TnyTestViewClass;
+
+struct _TnyTestView
+{
+	GObject parent;
+};
+
+struct _TnyTestViewClass
+{
+	GObjectClass parent;
+};
+
+static void
+tny_test_view_update (GUnitView *self)
+{
+}
+
+static void
+tny_test_view_set_test_runner (GUnitView *self, gpointer runner)
+{
+}
+
+static void
+tny_test_view_show (GUnitView *self)
+{
+}
+
+static void
+tny_test_view_reset (GUnitView *self)
+{
+}
+
+static void
+tny_test_view_failure (GUnitView *self, const gchar *msg)
+{
+    g_print ("%s\n", msg);
+}
+
+static void
+tny_test_view_error (GUnitView *self, const gchar *msg)
+{
+    g_print ("%s\n", msg);
+}
+
+static void
+tny_test_view_update_progressbar (GUnitView *self, gint fraction, const gchar *msg)
+{
+}
+
+static void
+tny_test_view_update_statusbar (GUnitView *view, const gchar *msg)
+{
+}
+
+
+static void 
+gunit_view_init (GUnitViewClass *class)
+{
+	class->update = tny_test_view_update;
+	class->set_test_runner = tny_test_view_set_test_runner;
+	class->show = tny_test_view_show;
+	class->reset = tny_test_view_reset;
+	class->failure = tny_test_view_failure;
+	class->error = tny_test_view_error;
+	class->update_progressbar = tny_test_view_update_progressbar;
+	class->update_statusbar = tny_test_view_update_statusbar;
+}
+
+static void 
+tny_test_view_finalize (GObject *object)
+{
+	(*parent_class->finalize) (object);
+}
+
+static void
+tny_test_view_class_init (TnyTestViewClass *class)
+{
+	GObjectClass *object_class;
+
+	parent_class = g_type_class_peek_parent (class);
+	object_class = (GObjectClass*) class;
+
+	object_class->finalize = tny_test_view_finalize;
+}
+
+
+GType 
+tny_test_view_get_type (void)
+{
+	static GType type = 0;
+
+	if (type == 0) 
+	{
+		static const GTypeInfo info = 
+		{
+		  sizeof (TnyTestViewClass),
+		  NULL,   /* base_init */
+		  NULL,   /* base_finalize */
+		  (GClassInitFunc) tny_test_view_class_init,   /* class_init */
+		  NULL,   /* class_finalize */
+		  NULL,   /* class_data */
+		  sizeof (TnyTestView),
+		  0,      /* n_preallocs */
+		  NULL    /* instance_init */
+		};
+
+		static const GInterfaceInfo gunit_view_info = 
+		{
+		  (GInterfaceInitFunc) gunit_view_init, /* interface_init */
+		  NULL,         /* interface_finalize */
+		  NULL          /* interface_data */
+		};
+
+		type = g_type_register_static (G_TYPE_OBJECT,
+			"TnyTestView",
+			&info, 0);
+
+		g_type_add_interface_static (type, GUNIT_TYPE_VIEW, 
+			&gunit_view_info);
+	}
+
+	return type;
+}
+
+int
+main (int argc, char **argv)
+{
+	GList *suites = NULL, *names = NULL;
+	GUnitTestRunner *runner = NULL;
+	GUnitView *view = NULL;
+
+    	gtk_init (&argc, &argv);
+	g_thread_init (NULL);
+
+	gtk_init (&argc, &argv);
+
+	view = GUNIT_VIEW (g_object_new (tny_test_view_get_type (), NULL));
+
+	runner = gunit_test_runner_get_instance ();
+
+	gunit_test_runner_set_view (runner, view);
+
+	suites = gunit_get_test_suites ();
+
+	while (suites)
+	{
+		gunit_test_runner_add_suite (runner, suites->data);
+		
+		suites = g_list_next (suites);
+	}
+
+	g_list_free (suites);
+
+	names = gunit_test_runner_get_suite_name_list (runner);
+
+	while (names)
+	{
+		const gchar *name = (const gchar*)names->data;
+
+		g_print ("Unit test runner runs %s\n", name);
+		gunit_test_runner_run_suite (runner, name);
+
+		names = g_list_next (names);
+	}
+
+	g_list_free (names);
+
+	return 0;
+}
Index: libtinymail-test/.svnignore
===================================================================
--- libtinymail-test/.svnignore	(revisjon 1252)
+++ libtinymail-test/.svnignore	(arbeidskopi)
@@ -4,3 +4,4 @@
 tny-simple-test-runner
 tny-test-anything
 .libs
+tny-simple-api-test-runner
Index: libtinymail-test/Makefile.am
===================================================================
--- libtinymail-test/Makefile.am	(revisjon 1252)
+++ libtinymail-test/Makefile.am	(arbeidskopi)
@@ -17,6 +17,11 @@
 
 bin_PROGRAMS = tny-simple-test-runner tny-test-anything
 
+if BUILD_APITESTS
+lib_LTLIBRARIES += libtinymail-api-test-suite.la
+bin_PROGRAMS += tny-simple-api-test-runner
+endif
+
 libtinymail_test_suite_la_SOURCES = \
 	tny-folder-store-query-test.c \
 	tny-folder-store-query-test.h \
@@ -91,3 +96,35 @@
 	$(top_builddir)/tests/shared/libtestsshared.a \
 	libtinymail-test-suite.la
 
+# API test suite
+
+libtinymail_api_test_suite_la_SOURCES = \
+	tny-api-test-suite.c \
+	tny-list-test.c \
+	tny-device-test.c \
+	tny-account-test.c \
+	tny-folder-test.c \
+	tny-mime-part-test.c \
+	tny-test-stream.c \
+	tny-header-test.c \
+	tny-folder-store-query-test.c \
+	tny-account-store-test.c \
+	tny-platform-factory-test.c \
+	tny-test-object.c
+
+libtinymail_api_test_suite_la_CFLAGS = -fPIC \
+	$(LIBTINYMAIL_API_TEST_CFLAGS)
+
+libtinymail_api_test_suite_la_LDFLAGS = $(LIBTINYMAIL_API_TEST_LIBS) \
+	-export-dynamic -version-info $(LT_VERSION_INFO) \
+	$(LIBTOOL_EXPORT_OPTIONS)
+
+# API test runner
+
+tny_simple_api_test_runner_SOURCES = tny-simple-api-test-runner.c
+
+tny_simple_api_test_runner_CFLAGS = $(LIBTINYMAIL_API_TEST_CFLAGS)
+
+tny_simple_api_test_runner_LDADD = \
+	libtinymail-api-test-suite.la \
+	$(top_builddir)/tests/shared/libtestsshared.a
Index: configure.ac
===================================================================
--- configure.ac	(revisjon 1252)
+++ configure.ac	(arbeidskopi)
@@ -169,6 +169,20 @@
 esac],[build_gnome=$build_gnome])
 AM_CONDITIONAL(BUILD_GNOME, test x$build_gnome = xtrue)
 
+dnl ### Enable building the API tests ##
+AC_ARG_ENABLE(api-tests,
+AC_HELP_STRING([--enable-api-tests],
+  [Build API tests (no, yes)]),
+[case "${enableval}" in
+  yes) 
+	build_apitests=true 
+	build_unittests=true 
+  ;;
+  no)  build_apitests=false ;;
+  *) AC_MSG_ERROR(bad value ${enableval} for --enable-api-tests) ;;
+esac],[build_apitests=$build_apitests])
+AM_CONDITIONAL(BUILD_APITESTS, test x$build_apitests = xtrue)
+
 dnl ### Enable building the unit tests ##
 AC_ARG_ENABLE(unit-tests,
 AC_HELP_STRING([--enable-unit-tests],
@@ -341,6 +355,16 @@
 AC_SUBST(LIBTINYMAIL_TEST_CFLAGS)
 AC_SUBST(LIBTINYMAIL_TEST_LIBS)
 
+dnl ### libtinymail-api-test, a library for testing API/ABI compatibility ##
+if test x$build_apitests = xtrue; then
+  PKG_CHECK_MODULES(LIBTINYMAIL_API_TEST, gunit glib-2.0 >= 2.6 gobject-2.0 libtinymail-1.0 libtinymail-camel-1.0 libtinymailui-gtk-1.0 camel-lite-1.2)
+else
+  LIBTINYMAIL_API_TEST_CFLAGS=
+  LIBTINYMAIL_API_TEST_LIBS=
+fi
+AC_SUBST(LIBTINYMAIL_API_TEST_CFLAGS)
+AC_SUBST(LIBTINYMAIL_API_TEST_LIBS)
+
 dnl ### tinymail, the demo-ui ##
 PKG_CHECK_MODULES(TINYMAIL, glib-2.0 >= 2.6 gobject-2.0 gtk+-2.0 $extratnypkgs)
 AC_SUBST(TINYMAIL_CFLAGS)
@@ -415,6 +439,7 @@
 echo "  Enable GNOME features:       $build_gnome"
 echo "  HTML component:              ${with_html_component}"
 echo "  Python language bindings:    $build_pytinymail"
+echo "  API tests:                   $build_apitests"
 echo "  Unit tests:                  $build_unittests"
 echo "  Tests:                       $build_tests"
 echo "  Target platform:             ${with_platform}"
Index: README
===================================================================
--- README	(revisjon 1252)
+++ README	(arbeidskopi)
@@ -33,6 +33,15 @@
   export LD_LIBRARY_PATH=./libtinymail-test/.libs/
   gunit-test-runner-tool -s tinymail-test-suite -v gnome
 
+API tests are unit tests that test only the public interface of tinymail.
+Instead of testing the current source, it will test the tinymail libraries
+currently installed on the system. Enable API tests with --enable-api-tests.
+Tinymail .pc files must be found by pkg-config when using this flag.
+
+API test usage
+  export LD_LIBRARY_PATH=./libtinymail-test/.libs/
+  gunit-test-runner-tool -s tinymail-api-test-suite -v gnome
+
 Building tips
 =============
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]