[gdm-list] automated unit testing in GDM



Hi,

Attached is a proposed patch (against the SVN trunk) to bring unit testing and its benefits to GDM. Even though I otherwise prefer CppUnit, I chose check against CppUnit simply because the CppUnit requires a C++ compiler and check does not. Another attached patch allow the initial tests to pass.

Accepting unit testing into GDM implies writing more tests, maintaining the tests, fixing code to pass the tests, refactoring code into testable pieces, documenting code, etc. At a glance, it appears GDM may be already undergoing some of these changes. In the future, it would be helpful to conditionally include check into configure.ac, so that it is possible to run "./configure; make" without check.


Andrew
Index: tests/checkgdm.c
===================================================================
--- tests/checkgdm.c	(revision 0)
+++ tests/checkgdm.c	(revision 0)
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 Andrew Ziem
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: Andrew Ziem
+ *
+ */
+
+
+#include <check.h>
+#include <glib-object.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "checkgdm.h"
+
+int
+main (int argc, char *argv[])
+{
+	SRunner *sr;
+	int i;
+	enum print_output print_mode = CK_NORMAL;
+
+
+	g_type_init();
+
+	int number_failed;
+	Suite *suite_gdm_address = gdm_address_suite ();
+	Suite *suite_gdm_common = gdm_common_suite ();
+	sr = srunner_create (suite_gdm_address);
+	srunner_add_suite (sr, suite_gdm_common);
+	for (i = 0; i < argc; i++)
+	{
+		if (0 == strncmp(argv[i], "--nofork", 9))
+			srunner_set_fork_status (sr, CK_NOFORK);
+		else if (0 == strncmp(argv[i], "--verbose", 10))
+			print_mode = CK_VERBOSE;
+	}
+	srunner_run_all (sr, print_mode);
+	number_failed = srunner_ntests_failed (sr);
+	srunner_free (sr);
+	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
Index: tests/gdm-address-check.c
===================================================================
--- tests/gdm-address-check.c	(revision 0)
+++ tests/gdm-address-check.c	(revision 0)
@@ -0,0 +1,245 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 Andrew Ziem
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: Andrew Ziem
+ *
+ */
+
+#include "config.h"
+
+#include <check.h>
+#include <glib.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "checkgdm.h"
+#include "gdm-address.h"
+
+
+GdmAddress *ga;
+GdmAddress *ga192;
+struct sockaddr sa;
+struct sockaddr_in *s_in;
+
+#ifdef ENABLE_IPV6
+GdmAddress *ga6;
+struct sockaddr_storage sa6;
+struct sockaddr_in6 *s_in6;
+#endif
+
+
+void setup (void);
+void teardown (void);
+
+
+void
+setup (void)
+{
+	s_in = (struct sockaddr_in *) &sa;
+	s_in->sin_family = AF_INET;
+	s_in->sin_port = htons(25);
+	s_in->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+	fail_unless ( NULL != (ga = gdm_address_new_from_sockaddr(&sa, sizeof(sa))));
+
+	s_in->sin_addr.s_addr = htonl(0xc0a80001); /* 192.168.0.1 */
+	fail_unless ( NULL != (ga192 = gdm_address_new_from_sockaddr(&sa, sizeof(sa))));
+
+#ifdef ENABLE_IPV6
+	s_in6 = (struct sockaddr_in6 *) &sa6;
+	s_in6->sin6_family = AF_INET6;
+	s_in6->sin6_port = htons(25);
+	s_in6->sin6_addr = in6addr_loopback;
+	fail_unless ( NULL != (ga6 = gdm_address_new_from_sockaddr((struct sockaddr*)&sa6, sizeof(sa6))));
+#endif
+}
+
+void
+teardown (void)
+{
+	gdm_address_free (ga);
+	gdm_address_free (ga192);
+#ifdef ENABLE_IPV6
+	gdm_address_free (ga6);
+#endif
+}
+
+
+/* 
+ * GType                    gdm_address_get_type                  (void);
+ */
+START_TEST (test_gdm_address_get_type)
+{
+	GType g;
+	g = gdm_address_get_type();
+	/* it did not crash! :) */
+
+}
+END_TEST
+
+
+/*
+GdmAddress *             gdm_address_new_from_sockaddr         (struct sockaddr *sa,
+                                                                size_t           size);
+*/
+START_TEST (test_gdm_address_new_from_sockaddr)
+{
+
+	GdmAddress *_ga;
+#ifdef ENABLE_IPV6
+	GdmAddress *_ga6;
+#endif
+
+	fail_unless ( NULL != (_ga = gdm_address_new_from_sockaddr((struct sockaddr *)&sa, sizeof(sa))) );
+	gdm_address_free (_ga);
+
+#ifdef ENABLE_IPV6
+	fail_unless ( NULL != (_ga6 = gdm_address_new_from_sockaddr((struct sockaddr *)&sa6, sizeof(sa6))) );
+	gdm_address_free (_ga6);
+#endif
+
+#ifndef NO_INVALID_INPUT
+	/* invalid input */
+	fail_unless ( NULL == gdm_address_new_from_sockaddr((struct sockaddr*)&sa, 1), NULL );
+	fail_unless ( NULL == gdm_address_new_from_sockaddr(NULL, 0), NULL);
+#endif
+}
+END_TEST
+
+/*
+int                      gdm_address_get_family_type           (GdmAddress              *address); */
+
+START_TEST (test_gdm_address_get_family_type)
+{
+	fail_unless ( AF_INET == gdm_address_get_family_type(ga), NULL);
+
+#ifdef ENABLE_IPV6
+	fail_unless ( AF_INET6 == gdm_address_get_family_type(ga6), NULL);
+#endif
+
+#ifndef NO_INVALID_INPUT
+	/* invalid input */
+	fail_unless ( -1 == gdm_address_get_family_type(NULL), NULL);
+#endif
+
+}
+END_TEST
+
+/*
+struct sockaddr_storage *gdm_address_get_sockaddr_storage      (GdmAddress              *address);
+struct sockaddr_storage *gdm_address_peek_sockaddr_storage     (GdmAddress              *address);
+
+gboolean                 gdm_address_get_hostname              (GdmAddress              *address,
+                                                                char                   **hostname);
+gboolean                 gdm_address_get_numeric_info          (GdmAddress              *address,
+                                                                char                   **numeric_hostname,
+                                                                char                   **service);
+gboolean                 gdm_address_is_local                  (GdmAddress              *address);
+*/
+
+/* 
+ * gboolean                 gdm_address_is_loopback               (GdmAddress              *address);
+ */
+START_TEST (test_gdm_address_is_loopback)
+{
+	fail_unless( TRUE == gdm_address_is_loopback(ga));
+	fail_unless( FALSE == gdm_address_is_loopback(ga192));
+
+#ifdef ENABLE_IPV6
+	fail_unless( TRUE == gdm_address_is_loopback(ga6));
+	/* FIXME: add more addresses */
+#endif
+
+#ifndef NO_INVALID_INPUT
+	/* invalid input */
+	fail_unless( FALSE == gdm_address_is_loopback(NULL));
+#endif
+}
+END_TEST
+
+/*
+ * gboolean                 gdm_address_equal                     (GdmAddress              *a,
+ *                                                                 GdmAddress              *b);
+ */
+START_TEST (test_gdm_address_equal)
+{
+	GdmAddress *gdm1;
+	struct sockaddr sa1;
+	struct sockaddr_in *sin1;
+
+	/* should be inequal */
+	sin1 = (struct sockaddr_in *) &sa1;
+	sin1->sin_family = AF_INET;
+	sin1->sin_addr.s_addr = htonl(0xc0a80001); /* 192.168.0.1 */
+	gdm1 = gdm_address_new_from_sockaddr(&sa1, sizeof(sa1));	
+	fail_unless (gdm_address_equal (ga, ga192) == FALSE, NULL);
+
+	/* should be equal */
+	fail_unless (TRUE == gdm_address_equal (ga192, gdm1), NULL);
+
+	gdm_address_free(gdm1);
+
+#ifdef ENABLE_IPV6
+	/* should be inequal */
+	fail_unless (FALSE == gdm_address_equal (ga6, ga), NULL);
+	fail_unless (FALSE == gdm_address_equal (ga6, ga192), NULL);
+	fail_unless (FALSE == gdm_address_equal (ga6, gdm1), NULL);
+
+	/* should be equal */
+ 	/* FIXME: ipv6 version too */
+#endif
+
+#ifndef NO_INVALID_INPUT
+	/* invalid input */
+	fail_unless (FALSE == gdm_address_equal(NULL, NULL), NULL);
+	fail_unless (FALSE == gdm_address_equal(ga, NULL), NULL);
+	fail_unless (FALSE == gdm_address_equal(NULL, ga), NULL);
+#endif
+}
+
+
+END_TEST
+
+/*
+GdmAddress *             gdm_address_copy                      (GdmAddress              *address);
+void                     gdm_address_free                      (GdmAddress              *address);
+
+
+void                     gdm_address_debug                     (GdmAddress              *address);
+
+const GList *            gdm_address_peek_local_list           (void);
+*/
+
+
+Suite *
+gdm_address_suite (void)
+{
+	Suite *s = suite_create ("gdm-address");
+	TCase *tc_core = tcase_create ("core");
+	tcase_add_checked_fixture (tc_core, setup, teardown);
+	tcase_add_test (tc_core, test_gdm_address_get_type);
+	tcase_add_test (tc_core, test_gdm_address_new_from_sockaddr);
+	tcase_add_test (tc_core, test_gdm_address_get_family_type);
+	tcase_add_test (tc_core, test_gdm_address_is_loopback);
+	tcase_add_test (tc_core, test_gdm_address_equal);
+	suite_add_tcase(s, tc_core);
+
+	return s;
+}
+
Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am	(revision 0)
+++ tests/Makefile.am	(revision 0)
@@ -0,0 +1,30 @@
+INCLUDES = \
+	-I. \
+	-I.. \
+	-I$(top_srcdir)/common \
+	$(COMMON_CFLAGS)
+
+noinst_PROGRAMS =	\
+	checkgdm	\
+	$(NULL)
+
+checkgdm_SOURCES =	\
+	checkgdm.c 	\
+	gdm-address-check.c	\
+	gdm-common-check.c	\
+	$(NULL)
+
+checkgdm_CFLAGS =  \
+	@CHECK_CFLAGS@ \
+	$(COMMON_CFLAGS) \
+	$(NULL)
+
+checkgdm_LDADD = 	\
+	@CHECK_LIBS@	\
+	$(COMMON_LIBS)	\
+	gdm-address-check.o	\
+	gdm-common-check.o	\
+	$(NULL)
+
+TESTS = checkgdm
+
Index: tests/gdm-common-check.c
===================================================================
--- tests/gdm-common-check.c	(revision 0)
+++ tests/gdm-common-check.c	(revision 0)
@@ -0,0 +1,91 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 Andrew Ziem
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: Andrew Ziem
+ *
+ */
+
+
+#include <check.h>
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "checkgdm.h"
+#include "gdm-common.h"
+
+/*
+ * void           gdm_set_fatal_warnings_if_unstable (void);
+ */
+
+/*
+int            gdm_signal_pid            (int pid,
+                                          int signal);
+*/
+
+/*
+gboolean       gdm_string_hex_encode     (const GString *source,
+                                          int            start,
+                                          GString       *dest,
+                                          int            insert_at);
+*/
+START_TEST (test_gdm_string_hex_encode)
+{
+	GString *a, *b;
+
+	a = g_string_new("foo");
+	b = g_string_sized_new(100);
+	fail_unless ( TRUE == gdm_string_hex_encode(a, 0, b, 0), NULL);
+	fail_unless ( 0 == strncmp(b->str, "666f6f", 7), NULL);
+
+#ifndef NO_INVALID_INPUT
+	/* invalid input */
+	fail_unless ( FALSE == gdm_string_hex_encode(a, -1, b, -1), NULL);
+	fail_unless ( FALSE == gdm_string_hex_encode(NULL, 0, NULL, 0), NULL);
+	fail_unless ( FALSE == gdm_string_hex_encode(a, 0, a, 0), NULL);
+#endif
+
+	g_string_free(a, TRUE);
+	g_string_free(b, TRUE);
+}
+END_TEST
+
+/*
+gboolean       gdm_string_hex_decode     (const GString *source,
+                                          int            start,
+                                          int           *end_return,
+                                          GString       *dest,
+                                          int            insert_at);
+*/
+
+
+
+Suite *
+gdm_common_suite (void)
+{
+	Suite *s = suite_create ("gdm-common");
+	TCase *tc_core = tcase_create ("core");
+
+	tcase_add_test (tc_core, test_gdm_string_hex_encode);
+
+	suite_add_tcase(s, tc_core);
+
+	return s;
+}
+
+
Index: tests/checkgdm.h
===================================================================
--- tests/checkgdm.h	(revision 0)
+++ tests/checkgdm.h	(revision 0)
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 Andrew Ziem
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: Andrew Ziem
+ *
+ */
+
+#ifndef __CHECKGDM_H
+#define __CHECKGDM_H
+
+#include <check.h>
+
+Suite * gdm_address_suite (void);
+Suite * gdm_common_suite (void);
+
+
+#endif
+
Index: configure.ac
===================================================================
--- configure.ac	(revision 5522)
+++ configure.ac	(working copy)
@@ -956,6 +956,11 @@
    AC_MSG_RESULT(no)
 fi
 
+# Unit testing framework called check
+#
+PKG_CHECK_MODULES([CHECK], [check >= 0.9.4])
+
+
 # Check for Solaris logindevperm support
 #
 AC_MSG_CHECKING(for Solaris di_devperm_login)
@@ -1322,6 +1327,7 @@
 data/pixmaps/48x48/Makefile
 common/Makefile
 po/Makefile.in
+tests/Makefile
 ])
 
 dnl ---------------------------------------------------------------------------
Index: Makefile.am
===================================================================
--- Makefile.am	(revision 5522)
+++ Makefile.am	(working copy)
@@ -7,6 +7,7 @@
 	gui 			\
 	utils 			\
 	po 			\
+	tests 			\
 	$(NULL)
 
 # add these when help gets added back
Index: common/gdm-address.c
===================================================================
--- common/gdm-address.c	(revision 5522)
+++ common/gdm-address.c	(working copy)
@@ -166,8 +166,10 @@
         guint8 fam_a;
         guint8 fam_b;
 
-        g_return_val_if_fail (a != NULL || a->ss != NULL, FALSE);
-        g_return_val_if_fail (b != NULL || b->ss != NULL, FALSE);
+        g_return_val_if_fail (a != NULL, FALSE);
+        g_return_val_if_fail (a->ss != NULL, FALSE);
+        g_return_val_if_fail (b != NULL, FALSE);
+        g_return_val_if_fail (b->ss != NULL, FALSE);
 
         fam_a = a->ss->ss_family;
         fam_b = b->ss->ss_family;
@@ -259,7 +261,8 @@
 gboolean
 gdm_address_is_loopback (GdmAddress *address)
 {
-        g_return_val_if_fail (address != NULL || address->ss != NULL, FALSE);
+        g_return_val_if_fail (address != NULL, FALSE);
+        g_return_val_if_fail (address->ss != NULL, FALSE);
 
         switch (address->ss->ss_family){
 #ifdef  AF_INET6
Index: common/gdm-common.c
===================================================================
--- common/gdm-common.c	(revision 5522)
+++ common/gdm-common.c	(working copy)
@@ -119,6 +119,11 @@
         const unsigned char *end;
         gboolean             retval;
 
+        g_return_val_if_fail (source != NULL, FALSE);
+        g_return_val_if_fail (dest != NULL, FALSE);
+        g_return_val_if_fail (source != dest, FALSE);
+        g_return_val_if_fail (start >= 0, FALSE);
+        g_return_val_if_fail (dest >= 0, FALSE);
         g_assert (start <= source->len);
 
         result = g_string_new (NULL);


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