aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Gould <ted@gould.cx>2012-09-20 08:39:53 +0000
committerTarmac <Unknown>2012-09-20 08:39:53 +0000
commit126edd829bbf88c1a2a186a874acb4a307f3b5a9 (patch)
tree877c48d3bef1123accafba2caa953d73bc2002c5
parentaa87c8fac598ef6e79a65d6f2eec93d8a4693063 (diff)
parent19c01abdd2c3a3d772cf8b7f54b819231ac4dcba (diff)
downloadlibpam-freerdp2-126edd829bbf88c1a2a186a874acb4a307f3b5a9.tar.gz
libpam-freerdp2-126edd829bbf88c1a2a186a874acb4a307f3b5a9.tar.bz2
libpam-freerdp2-126edd829bbf88c1a2a186a874acb4a307f3b5a9.zip
Adding a testing framework. Approved by Albert Astals Cid, jenkins.
-rw-r--r--Makefile.am4
-rw-r--r--Makefile.am.coverage48
-rw-r--r--configure.ac27
-rw-r--r--m4/gcov.m486
-rw-r--r--m4/gtest.m463
-rw-r--r--src/Makefile.am29
-rw-r--r--src/auth-check-path.c3
-rw-r--r--src/auth-check-path.h1
-rw-r--r--src/pam-freerdp.c4
-rw-r--r--tests/Makefile.am67
-rw-r--r--tests/mock_guest.c51
-rw-r--r--tests/mock_guest.h24
-rw-r--r--tests/mock_pam.c110
-rw-r--r--tests/mock_pam.h23
-rw-r--r--tests/test-freerdp-auth.c57
-rw-r--r--tests/test-freerdp-wrapper.cc76
16 files changed, 664 insertions, 9 deletions
diff --git a/Makefile.am b/Makefile.am
index 769ade8..9477c1c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,7 @@
SUBDIRS = \
- src
+ src \
+ tests
DISTCHECK_CONFIGURE_FLAGS = --enable-localinstall
@@ -30,3 +31,4 @@ dist-hook:
echo Failed to generate AUTHORS: not a branch >&2; \
fi
+include $(top_srcdir)/Makefile.am.coverage
diff --git a/Makefile.am.coverage b/Makefile.am.coverage
new file mode 100644
index 0000000..fb97747
--- /dev/null
+++ b/Makefile.am.coverage
@@ -0,0 +1,48 @@
+
+# Coverage targets
+
+.PHONY: clean-gcno clean-gcda \
+ coverage-html generate-coverage-html clean-coverage-html \
+ coverage-gcovr generate-coverage-gcovr clean-coverage-gcovr
+
+clean-local: clean-gcno clean-coverage-html clean-coverage-gcovr
+
+if HAVE_GCOV
+
+clean-gcno:
+ @echo Removing old coverage instrumentation
+ -find -name '*.gcno' -print | xargs -r rm
+
+clean-gcda:
+ @echo Removing old coverage results
+ -find -name '*.gcda' -print | xargs -r rm
+
+coverage-html: clean-gcda
+ -$(MAKE) $(AM_MAKEFLAGS) -k check
+ $(MAKE) $(AM_MAKEFLAGS) generate-coverage-html
+
+generate-coverage-html:
+ @echo Collecting coverage data
+ $(LCOV) --directory $(top_builddir) --capture --output-file coverage.info --no-checksum --compat-libtool
+ LANG=C $(GENHTML) --prefix $(top_builddir) --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info
+
+clean-coverage-html: clean-gcda
+ -$(LCOV) --directory $(top_builddir) -z
+ -rm -rf coverage.info coveragereport
+
+if HAVE_GCOVR
+
+coverage-gcovr: clean-gcda
+ -$(MAKE) $(AM_MAKEFLAGS) -k check
+ $(MAKE) $(AM_MAKEFLAGS) generate-coverage-gcovr
+
+generate-coverage-gcovr:
+ @echo Generating coverage GCOVR report
+ $(GCOVR) -x -r $(top_builddir) -o $(top_builddir)/coverage.xml
+
+clean-coverage-gcovr: clean-gcda
+ -rm -rf $(top_builddir)/coverage.xml
+
+endif # HAVE_GCOVR
+
+endif # HAVE_GCOV
diff --git a/configure.ac b/configure.ac
index aa8a3f9..cee665d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,6 +5,8 @@ AM_INIT_AUTOMAKE([1.11 -Wno-portability])
AM_SILENT_RULES([yes])
AC_PROG_CC
+# the Google Test targets are cpp
+AC_PROG_CXX
AC_PROG_LIBTOOL
LT_INIT([disable-static])
@@ -46,9 +48,34 @@ else
fi
AC_SUBST(PAMMODULEDIR)
+###########################
+# Google Test Dependencies
+###########################
+
+m4_include([m4/gtest.m4])
+CHECK_GTEST
+if test "x$have_gtest" != "xyes"; then
+ AC_MSG_ERROR([tests were requested but gtest is not installed.])
+fi
+
+###########################
+# gcov coverage reporting
+###########################
+
+m4_include([m4/gcov.m4])
+AC_TDD_GCOV
+AM_CONDITIONAL([HAVE_GCOV], [test "x$ac_cv_check_gcov" = xyes])
+AM_CONDITIONAL([HAVE_LCOV], [test "x$ac_cv_check_lcov" = xyes])
+AM_CONDITIONAL([HAVE_GCOVR], [test "x$ac_cv_check_gcovr" = xyes])
+AC_SUBST(COVERAGE_CFLAGS)
+AC_SUBST(COVERAGE_CXXFLAGS)
+AC_SUBST(COVERAGE_LDFLAGS)
+
+
AC_CONFIG_FILES([
Makefile
src/Makefile
+ tests/Makefile
])
AC_OUTPUT
diff --git a/m4/gcov.m4 b/m4/gcov.m4
new file mode 100644
index 0000000..3163584
--- /dev/null
+++ b/m4/gcov.m4
@@ -0,0 +1,86 @@
+# Checks for existence of coverage tools:
+# * gcov
+# * lcov
+# * genhtml
+# * gcovr
+#
+# Sets ac_cv_check_gcov to yes if tooling is present
+# and reports the executables to the variables LCOV, GCOVR and GENHTML.
+AC_DEFUN([AC_TDD_GCOV],
+[
+ AC_ARG_ENABLE(gcov,
+ AS_HELP_STRING([--enable-gcov],
+ [enable coverage testing with gcov]),
+ [use_gcov=$enableval], [use_gcov=no])
+
+ if test "x$use_gcov" = "xyes"; then
+ # we need gcc:
+ if test "$GCC" != "yes"; then
+ AC_MSG_ERROR([GCC is required for --enable-gcov])
+ fi
+
+ # Check if ccache is being used
+ AC_CHECK_PROG(SHTOOL, shtool, shtool)
+ case `$SHTOOL path $CC` in
+ *ccache*[)] gcc_ccache=yes;;
+ *[)] gcc_ccache=no;;
+ esac
+
+ if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then
+ AC_MSG_ERROR([ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.])
+ fi
+
+ lcov_version_list="1.6 1.7 1.8 1.9"
+ AC_CHECK_PROG(LCOV, lcov, lcov)
+ AC_CHECK_PROG(GENHTML, genhtml, genhtml)
+
+ if test "$LCOV"; then
+ AC_CACHE_CHECK([for lcov version], glib_cv_lcov_version, [
+ glib_cv_lcov_version=invalid
+ lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'`
+ for lcov_check_version in $lcov_version_list; do
+ if test "$lcov_version" = "$lcov_check_version"; then
+ glib_cv_lcov_version="$lcov_check_version (ok)"
+ fi
+ done
+ ])
+ else
+ lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list"
+ AC_MSG_ERROR([$lcov_msg])
+ fi
+
+ case $glib_cv_lcov_version in
+ ""|invalid[)]
+ lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)."
+ AC_MSG_ERROR([$lcov_msg])
+ LCOV="exit 0;"
+ ;;
+ esac
+
+ if test -z "$GENHTML"; then
+ AC_MSG_ERROR([Could not find genhtml from the lcov package])
+ fi
+
+ ac_cv_check_gcov=yes
+ ac_cv_check_lcov=yes
+
+ # Remove all optimization flags from CFLAGS
+ changequote({,})
+ CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'`
+ changequote([,])
+
+ # Add the special gcc flags
+ COVERAGE_CFLAGS="-O0 -fprofile-arcs -ftest-coverage"
+ COVERAGE_CXXFLAGS="-O0 -fprofile-arcs -ftest-coverage"
+ COVERAGE_LDFLAGS="-lgcov"
+
+ # Check availability of gcovr
+ AC_CHECK_PROG(GCOVR, gcovr, gcovr)
+ if test -z "$GCOVR"; then
+ ac_cv_check_gcovr=no
+ else
+ ac_cv_check_gcovr=yes
+ fi
+
+fi
+]) # AC_TDD_GCOV
diff --git a/m4/gtest.m4 b/m4/gtest.m4
new file mode 100644
index 0000000..2de334c
--- /dev/null
+++ b/m4/gtest.m4
@@ -0,0 +1,63 @@
+# Copyright (C) 2012 Canonical, Ltd.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+# Checks whether the gtest source is available on the system. Allows for
+# adjusting the include and source path. Sets have_gtest=yes if the source is
+# present. Sets GTEST_CPPFLAGS and GTEST_SOURCE to the preprocessor flags and
+# source location respectively.
+AC_DEFUN([CHECK_GTEST],
+[
+ AC_ARG_WITH([gtest-include-path],
+ [AS_HELP_STRING([--with-gtest-include-path],
+ [location of the Google test headers])],
+ [GTEST_CPPFLAGS="-I$withval"])
+
+ AC_ARG_WITH([gtest-source-path],
+ [AS_HELP_STRING([--with-gtest-source-path],
+ [location of the Google test sources, defaults to /usr/src/gtest])],
+ [GTEST_SOURCE="$withval"],
+ [GTEST_SOURCE="/usr/src/gtest"])
+
+ GTEST_CPPFLAGS="$GTEST_CPPFLAGS -I$GTEST_SOURCE"
+
+ AC_LANG_PUSH([C++])
+
+ tmp_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $GTEST_CPPFLAGS"
+
+ AC_CHECK_HEADER([gtest/gtest.h])
+
+ CPPFLAGS="$tmp_CPPFLAGS"
+
+ AC_LANG_POP
+
+ AC_CHECK_FILES([$GTEST_SOURCE/src/gtest-all.cc]
+ [$GTEST_SOURCE/src/gtest_main.cc],
+ [have_gtest_source=yes],
+ [have_gtest_source=no])
+
+ AS_IF([test "x$ac_cv_header_gtest_gtest_h" = xyes -a \
+ "x$have_gtest_source" = xyes],
+ [have_gtest=yes]
+ [AC_SUBST(GTEST_CPPFLAGS)]
+ [AC_SUBST(GTEST_SOURCE)],
+ [have_gtest=no])
+]) # CHECK_GTEST
diff --git a/src/Makefile.am b/src/Makefile.am
index e5b04b2..0fafb8a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,19 +3,31 @@ pamlibdir = $(PAMMODULEDIR)
pamlib_LTLIBRARIES = pam_freerdp.la
pam_freerdp_la_SOURCES = \
- pam-freerdp.c
+ auth-check-path.c auth-check-path.h
pam_freerdp_la_LDFLAGS = \
-no-undefined \
-module \
- -avoid-version
-
-pam_freerdp_la_LIBADD = \
- -lpam
+ -avoid-version \
+ $(COVERAGE_LDFLAGS)
pam_freerdp_la_CFLAGS = \
-Wall -Werror \
- -DAUTH_CHECK="\"$(pkglibexecdir)/freerdp-auth-check\""
+ -DAUTH_CHECK="\"$(pkglibexecdir)/freerdp-auth-check\"" \
+ $(COVERAGE_CFLAGS)
+
+noinst_LTLIBRARIES = \
+ libfreerdpcore.la
+
+libfreerdpcore_la_SOURCES = \
+ pam-freerdp.c
+libfreerdpcore_la_CFLAGS = \
+ -Wall -Werror \
+ $(COVERAGE_CFLAGS)
+libfreerdpcore_la_LIBADD = \
+ -lpam
+libfreerdpcore_la_LDFLAGS = \
+ $(COVERAGE_LDFLAGS)
pkglibexec_PROGRAMS = \
freerdp-auth-check
@@ -23,6 +35,9 @@ pkglibexec_PROGRAMS = \
freerdp_auth_check_SOURCES = \
freerdp-auth-check.c
freerdp_auth_check_CFLAGS = \
- $(FREERDP_CFLAGS)
+ $(FREERDP_CFLAGS) \
+ $(COVERAGE_CFLAGS)
freerdp_auth_check_LDADD = \
$(FREERDP_LIBS)
+freerdp_auth_check_LDFLAGS = \
+ $(COVERAGE_LDFLAGS)
diff --git a/src/auth-check-path.c b/src/auth-check-path.c
new file mode 100644
index 0000000..db311ea
--- /dev/null
+++ b/src/auth-check-path.c
@@ -0,0 +1,3 @@
+
+const char * auth_check_path = AUTH_CHECK;
+
diff --git a/src/auth-check-path.h b/src/auth-check-path.h
new file mode 100644
index 0000000..82deca2
--- /dev/null
+++ b/src/auth-check-path.h
@@ -0,0 +1 @@
+extern const char * auth_check_path;
diff --git a/src/pam-freerdp.c b/src/pam-freerdp.c
index 607e215..fbfe182 100644
--- a/src/pam-freerdp.c
+++ b/src/pam-freerdp.c
@@ -34,6 +34,8 @@
#include <security/pam_modutil.h>
#include <security/pam_appl.h>
+#include "auth-check-path.h"
+
#define PAM_TYPE_DOMAIN 1234
#define ALL_GOOD_SIGNAL "Ar, ready to authenticate cap'n"
@@ -238,7 +240,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, const char **argv)
char * args[5];
- args[0] = AUTH_CHECK;
+ args[0] = (char *)auth_check_path;
args[1] = rhost;
args[2] = ruser;
args[3] = rdomain;
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..c257ac9
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,67 @@
+CLEANFILES =
+DISTCLEANFILES =
+EXTRA_DIST =
+
+TESTS = \
+ test-freerdpclient-wrapper
+
+check_PROGRAMS = \
+ test-freerdp-auth \
+ $(TESTS)
+
+AM_CPPFLAGS = $(GTEST_CPPFLAGS) \
+ $(REMOTE_APPS_MANAGER_CFLAGS) \
+ -I${top_srcdir}/src -Wall -Werror
+AM_CXXFLAGS = $(GTEST_CXXFLAGS) \
+ $(REMOTE_APPS_MANAGER_CFLAGS)
+
+AM_CFLAGS = \
+ -Wall \
+ -g
+
+##########################
+# Google Test Test Suite #
+##########################
+
+check_LIBRARIES = libgtest.a
+
+nodist_libgtest_a_SOURCES = \
+ $(GTEST_SOURCE)/src/gtest-all.cc \
+ $(GTEST_SOURCE)/src/gtest_main.cc
+
+libgtest_a_CPPFLAGS = \
+ $(GTEST_CPPFLAGS) -w \
+ $(AM_CPPFLAGS)
+libgtest_a_CXXFLAGS = \
+ $(AM_CXXFLAGS)
+
+##########################
+# Wrapper
+##########################
+
+test_freerdp_wrapper: test-freerdp-auth
+
+test_freerdpclient_wrapper_SOURCES = \
+ mock_pam.c mock_pam.h \
+ mock_guest.c mock_guest.h \
+ test-freerdp-wrapper.cc
+
+test_freerdpclient_wrapper_LDADD = \
+ $(top_builddir)/src/libfreerdpcore.la \
+ libgtest.a
+
+test_freerdpclient_wrapper_CXXFLAGS = \
+ $(AM_CXXFLAGS) \
+ -DAUTH_CHECK="\"$(abs_builddir)/test-freerdp-auth\"" \
+ -I${top_srcdir}/src
+
+test_freerdpclient_wrapper_LDFLAGS = \
+ -pthread
+
+##########################
+# Auth tool
+##########################
+
+test_freerdp_auth_SOURCES = \
+ test-freerdp-auth.c
+
diff --git a/tests/mock_guest.c b/tests/mock_guest.c
new file mode 100644
index 0000000..2cf04b3
--- /dev/null
+++ b/tests/mock_guest.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright © 2012 Canonical Ltd. All rights reserved.
+ *
+ * Author(s): David Barth <david.barth@canonical.com>
+ *
+ */
+
+#include <pwd.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+static struct passwd guest = { "guest",
+ "password",
+ 500, 500,
+ "M. Guest",
+ "/tmp",
+ "/bin/true" };
+struct passwd *
+getpwnam (const char *username)
+{ return &guest; }
+
+int
+setgroups(size_t size, const gid_t *list)
+{
+ errno = EPERM;
+ return -1;
+}
+
+int
+setgid(gid_t gid)
+{ return 0; }
+
+int
+setuid(uid_t uid)
+{ return 0; }
+
+int
+setegid(gid_t gid)
+{ return 0; }
+
+int
+seteuid(uid_t uid)
+{ return 0; }
+
+int chmod(const char *path, mode_t mode)
+{ return 0; }
+
+int chown(const char *path, uid_t owner, gid_t group)
+{ return 0; }
+
diff --git a/tests/mock_guest.h b/tests/mock_guest.h
new file mode 100644
index 0000000..c4179b9
--- /dev/null
+++ b/tests/mock_guest.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2012 Canonical Ltd. All rights reserved.
+ *
+ * Author(s): David Barth <david.barth@canonical.com>
+ *
+ */
+
+#ifndef __MOCK_GUEST_H__
+#define __MOCK_GUEST_H__
+
+#include <pwd.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+struct passwd *getpwnam (const char *username);
+int setgroups(size_t size, const gid_t *list);
+int setgid(gid_t gid);
+int setuid(uid_t uid);
+int setegid(gid_t gid);
+int seteuid(uid_t uid);
+int chmod(const char *path, mode_t mode);
+int chown(const char *path, uid_t owner, gid_t group);
+
+#endif
diff --git a/tests/mock_pam.c b/tests/mock_pam.c
new file mode 100644
index 0000000..6368b84
--- /dev/null
+++ b/tests/mock_pam.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright © 2012 Canonical Ltd. All rights reserved.
+ *
+ * Author(s): David Barth <david.barth@canonical.com>
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "mock_pam.h"
+
+struct pam_handle {
+ void *item[PAM_NUM_ITEMS];
+
+ struct pam_conv *conv;
+
+ /* note: the other fields have been omitted */
+};
+
+int fake_conv (int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, void *appdata_ptr)
+{
+ struct pam_response *response = NULL;
+ response = malloc (sizeof (struct pam_response));
+
+ if (response == NULL)
+ return PAM_BUF_ERR;
+
+ response->resp_retcode = 0;
+
+ if (strcmp((*msg)->msg, "login:") == 0)
+ response->resp = strdup ("guest"); /* IMPORTANT: this needs to be in /etc/passwd */
+ else if (strcmp((*msg)->msg, "remote login:") == 0)
+ response->resp = strdup ("ruser");
+ else if (strcmp((*msg)->msg, "remote host:") == 0)
+ response->resp = strdup ("protocol://rhost/dummy");
+ else if (strcmp((*msg)->msg, "password:") == 0)
+ response->resp = strdup ("password");
+ else if (strcmp((*msg)->msg, "domain:") == 0)
+ response->resp = strdup ("domain");
+ else
+ return PAM_SYMBOL_ERR; /* leaks... */
+
+ *resp = response;
+
+ return PAM_SUCCESS;
+}
+
+struct pam_conv static_conv = { &fake_conv, (void *)NULL };
+
+pam_handle_t *pam_handle_new (void)
+{
+ pam_handle_t *newh = malloc (sizeof (pam_handle_t));
+
+ if (newh != NULL) {
+ newh->conv = &static_conv;
+ memset(newh->item, 0, sizeof(void *) * PAM_NUM_ITEMS);
+ }
+
+ return newh;
+}
+
+int pam_get_item (const pam_handle_t *pamh, int type, const void **value)
+{
+ if (pamh == NULL)
+ return PAM_SYSTEM_ERR;
+
+ if (type == PAM_CONV)
+ *value = pamh->conv;
+ else if (pamh->item[type] != NULL)
+ *value = pamh->item[type];
+ else
+ *value = NULL; /* will result in a prompt conversation */
+
+ return PAM_SUCCESS;
+}
+
+int pam_set_item (pam_handle_t *pamh, int type, const void *value)
+{
+ if (pamh == NULL)
+ return PAM_SYSTEM_ERR;
+
+ void **slot, *tmp;
+ size_t nsize, osize;
+
+ slot = &pamh->item[type];
+ osize = nsize = 0;
+
+ if (*slot != NULL)
+ osize = strlen((const char *)*slot) + 1;
+ if (value != NULL)
+ nsize = strlen((const char *)value) + 1;
+
+ if (*slot != NULL) {
+ memset(*slot, 0xd0, osize);
+ free(*slot);
+ }
+
+ if (value != NULL) {
+ if ((tmp = malloc(nsize)) == NULL)
+ return PAM_BUF_ERR;
+ memcpy(tmp, value, nsize);
+ } else {
+ tmp = NULL;
+ }
+ *slot = tmp;
+
+ return PAM_SUCCESS;
+}
diff --git a/tests/mock_pam.h b/tests/mock_pam.h
new file mode 100644
index 0000000..eb88a2e
--- /dev/null
+++ b/tests/mock_pam.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2012 Canonical Ltd. All rights reserved.
+ *
+ * Author(s): David Barth <david.barth@canonical.com>
+ *
+ */
+
+#ifndef __MOCK_PAM_H__
+#define __MOCK_PAM_H__
+
+#include <security/pam_modules.h>
+#include <security/pam_modutil.h>
+#include <security/pam_appl.h>
+
+#define PAM_NUM_ITEMS PAM_AUTHTOK_TYPE
+
+typedef struct pam_handle pam_handle_t;
+
+pam_handle_t *pam_handle_new (void);
+int pam_get_item (const pam_handle_t *pamh, int type, const void **value);
+int pam_set_item (pam_handle_t *pamh, int type, const void *value);
+
+#endif
diff --git a/tests/test-freerdp-auth.c b/tests/test-freerdp-auth.c
new file mode 100644
index 0000000..a83885e
--- /dev/null
+++ b/tests/test-freerdp-auth.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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/>.
+ *
+ * Author: Ted Gould <ted@canonical.com>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+main (int argc, char * argv[])
+{
+ char password[512];
+ if (argc != 4) {
+ printf("Not enough params");
+ return -1;
+ }
+
+ if (scanf("%511s", password) != 1) {
+ return -1;
+ }
+
+ /* Check username */
+ if (strcmp(argv[2], "ruser")) {
+ return -1;
+ }
+
+ /* Check password */
+ if (strcmp(password, "password")) {
+ return -1;
+ }
+
+ /* Check domain */
+ if (strcmp(argv[3], "domain")) {
+ return -1;
+ }
+
+ /* Check hostname */
+ if (strcmp(argv[1], "rhost")) {
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tests/test-freerdp-wrapper.cc b/tests/test-freerdp-wrapper.cc
new file mode 100644
index 0000000..cfe86de
--- /dev/null
+++ b/tests/test-freerdp-wrapper.cc
@@ -0,0 +1,76 @@
+/*
+ * Copyright © 2012 Canonical Ltd. All rights reserved.
+ *
+ * Author(s): David Barth <david.barth@canonical.com>
+ *
+ */
+
+#include <gtest/gtest.h>
+
+extern "C" {
+
+#include "mock_pam.h"
+#include "mock_guest.h"
+
+ int freerdpclient_wrapper (int argc, char * argv[]);
+
+const char * auth_check_path = AUTH_CHECK;
+
+}
+
+namespace {
+
+ // The fixture for testing class Foo.
+ class FreerdpclientWrapperTest : public ::testing::Test {
+ protected:
+ // You can remove any or all of the following functions if its body
+ // is empty.
+
+ FreerdpclientWrapperTest() {
+ // You can do set-up work for each test here.
+ setenv("HOME", "/tmp", 1 /* overwrite */);
+ }
+
+ virtual ~FreerdpclientWrapperTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ unlink("/tmp/.freerdp-socket");
+ }
+
+ virtual void TearDown() {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ unlink("/tmp/.freerdp-socket");
+ }
+
+ // Objects declared here can be used by all tests in the test case for Foo.
+ };
+
+ TEST_F(FreerdpclientWrapperTest, canLinkTheWholeGang) {
+ EXPECT_EQ (1, 1); // right, that's trivial, but that means
+ // that I got all of the wrapper and pam to link there
+ }
+
+ TEST_F(FreerdpclientWrapperTest, canCallPamOpenSession) {
+ const char *argv[] = { NULL };
+
+ pam_handle_t *pamh = pam_handle_new ();
+
+ EXPECT_EQ (PAM_SUCCESS,
+ pam_sm_authenticate (pamh, 0, 0, argv));
+ EXPECT_EQ (PAM_SUCCESS,
+ pam_sm_setcred (pamh, 0, 0, argv));
+ EXPECT_EQ (PAM_SUCCESS,
+ pam_sm_open_session (pamh, 0, 0, argv));
+ EXPECT_EQ (PAM_SUCCESS,
+ pam_sm_close_session (pamh, 0, 0, argv));
+ }
+
+}