]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Rework the vmrpcdbg library to use CUnit.
authorVMware, Inc <>
Wed, 20 Jan 2010 21:27:24 +0000 (13:27 -0800)
committerMarcelo Vanzin <mvanzin@vmware.com>
Wed, 20 Jan 2010 21:27:24 +0000 (13:27 -0800)
CUnit provides nicer ways to track test failures than just logging or
using hard asserts. So use CUnit to run vmtoolsd-based test code.

This required a few changes:

. to be able to use CUnit, the vmtoolsd main loop needs to be run in
the context of a CUnit test. So the code in mainLoop.c was reorganized
a bit so that all code that touches plugin code is run in that context,
and execution of the main loop is done through the vmrpcdbg library
(which sets up the CUnit context) when running in debug mode.

. the interface of the vmrpcdbg library was cleaned up a little bit.

. test code was changed to use CUnit asserts instead of
ASSERT/g_assert/logs.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
14 files changed:
open-vm-tools/Makefile.am
open-vm-tools/configure.ac
open-vm-tools/lib/include/vmware/tools/rpcdebug.h
open-vm-tools/services/vmtoolsd/mainLoop.c
open-vm-tools/services/vmtoolsd/mainPosix.c
open-vm-tools/services/vmtoolsd/toolsCoreInt.h
open-vm-tools/tests/testDebug/Makefile.am
open-vm-tools/tests/testDebug/testDebug.c
open-vm-tools/tests/testPlugin/Makefile.am
open-vm-tools/tests/testPlugin/testPlugin.c
open-vm-tools/tests/vmrpcdbg/Makefile.am
open-vm-tools/tests/vmrpcdbg/debugChannel.c
open-vm-tools/tests/vmrpcdbg/vmrpcdbg.c
open-vm-tools/tests/vmrpcdbg/vmrpcdbgInt.h [new file with mode: 0644]

index d9d7da3c93debae33aec8aa85853a8c869228541..7ab65fc92ffa751b7bd39ddb916530afe1d853b7 100644 (file)
@@ -47,7 +47,9 @@ if HAVE_FUSE
    SUBDIRS += vmblock-fuse
 endif
 SUBDIRS += xferlogs
-SUBDIRS += tests
+if ENABLE_TESTS
+   SUBDIRS += tests
+endif
 if WITH_KERNEL_MODULES
    SUBDIRS += modules
 endif
index 43e1cbbfdba54fac8505e4be38c0216f917fb9d5..264e5e75960b1cd3c27b25875979f61618d68606 100644 (file)
@@ -203,6 +203,14 @@ AC_ARG_ENABLE(
    [enable_docs="$enableval"],
    [enable_docs="yes"])
 
+AC_ARG_ENABLE(
+   tests,
+   AS_HELP_STRING(
+      [--disable-tests],
+      [disable compilation of test code.]),
+   [enable_tests="$enableval"],
+   [enable_tests="auto"])
+
 # If we're not going to use Gtk 2.0, disable Unity.
 if test "$with_gtk2" != "yes"; then
    enable_unity="no"
@@ -394,6 +402,27 @@ if test "$os" = "linux"; then
    fi
 fi
 
+#
+# Check for CUnit and disable test code if not available.
+#
+if test "$enable_tests" = "auto" -o "$enable_tests" = "yes"; then
+   AC_VMW_CHECK_LIB([cunit],
+                    [CUNIT],
+                    [],
+                    [],
+                    [],
+                    [CUnit/CUnit.h],
+                    [CU_initialize_registry],
+                    [have_cunit=yes],
+                    [have_cunit=no])
+   if test "$have_cunit" = "no"; then
+      if test "$enable_tests" = "yes"; then
+         AC_VMW_LIB_ERROR([CUNIT], [cunit])
+      else
+         AC_MSG_WARN([CUnit not found, tests won't be compiled.])
+      fi
+   fi
+fi
 
 # If the user explicitly disables X11, then don't try to detect the X-related libraries
 if test "$have_x" = "disabled"; then
@@ -1076,6 +1105,7 @@ AM_CONDITIONAL(HAVE_X11, test "$have_x" = "yes")
 AM_CONDITIONAL(HAVE_ICU, test "$with_icu" = "yes")
 AM_CONDITIONAL(WITH_KERNEL_MODULES, test "$with_kernel_modules" = "yes")
 AM_CONDITIONAL(ENABLE_UNITY, test "$enable_unity" = "yes")
+AM_CONDITIONAL(ENABLE_TESTS, test "$have_cunit" = "yes")
 AM_CONDITIONAL(WITH_ROOT_PRIVILEGES, test "$with_root_privileges" = "yes")
 AM_CONDITIONAL(HAVE_DOXYGEN, test "$have_doxygen" = "yes")
 AM_CONDITIONAL(HAVE_FUSE, test "$have_fuse" = "yes")
index 3e00ce17d9169e84381cef4178587bfa365d2c62..04f2c9b4409e88625c17960f9214082f45d5cc83 100644 (file)
 
 #include "vmware/tools/plugin.h"
 
+
+/**
+ * Shorthand macro to both call CU_ASSERT() and return from the
+ * function if the assertion fails. Note that this file doesn't
+ * include CUnit.h, so you'll need to include that header to use
+ * this macro.
+ */
+#define RPCDEBUG_ASSERT(test, retval) do {   \
+   CU_ASSERT(test);                          \
+   g_return_val_if_fail(test, retval);       \
+} while (0)
+
+
 struct RpcDebugPlugin;
 
 /**
@@ -125,8 +138,12 @@ struct RpcDebugLibData;
  * the library to use the debugging functionality.
  */
 typedef struct RpcDebugLibData {
-   RpcChannel *    (*newDebugChannel)  (ToolsAppCtx *, struct RpcDebugLibData *);
-   void            (*shutdown)         (ToolsAppCtx *, struct RpcDebugLibData *);
+   RpcChannel *    (*newDebugChannel)  (ToolsAppCtx *,
+                                        struct RpcDebugLibData *);
+   int             (*run)              (ToolsAppCtx *,
+                                        gpointer runMainLoop,
+                                        gpointer runData,
+                                        struct RpcDebugLibData *);
    RpcDebugPlugin   *debugPlugin;
 } RpcDebugLibData;
 
@@ -146,10 +163,6 @@ RpcDebugLibData *
 RpcDebug_Initialize(ToolsAppCtx *ctx,
                     gchar *dbgPlugin);
 
-RpcChannel *
-RpcDebug_NewDebugChannel(ToolsAppCtx *ctx,
-                         RpcDebugLibData *data);
-
 gboolean
 RpcDebug_SendNext(RpcDebugMsgMapping *rpcdata,
                   RpcDebugMsgList *list);
@@ -159,10 +172,6 @@ RpcDebug_SetResult(const char *str,
                    char **res,
                    size_t *len);
 
-void
-RpcDebug_Shutdown(ToolsAppCtx *ctx,
-                  RpcDebugLibData *data);
-
 G_END_DECLS
 
 /** @} */
index 476e657299db7e58d5089c0250f2088ee18d5c9f..0a039f6f41da2d5b2edf1b49194278f682f285e8 100644 (file)
 #include "vmware/tools/utils.h"
 
 
+/*
+ ******************************************************************************
+ * ToolsCoreCleanup --                                                  */ /**
+ *
+ * Cleans up the main loop after it has executed. After this function
+ * returns, the fields of the state object shouldn't be used anymore.
+ *
+ * @param[in]  state       Service state.
+ *
+ ******************************************************************************
+ */
+
+static void
+ToolsCoreCleanup(ToolsServiceState *state)
+{
+   ToolsCore_UnloadPlugins(state);
+   if (state->ctx.rpc != NULL) {
+      RpcChannel_Destroy(state->ctx.rpc);
+      state->ctx.rpc = NULL;
+   }
+   g_key_file_free(state->ctx.config);
+   g_main_loop_unref(state->ctx.mainLoop);
+
+#if defined(G_PLATFORM_WIN32)
+   if (state->ctx.comInitialized) {
+      CoUninitialize();
+      state->ctx.comInitialized = FALSE;
+   }
+#endif
+
+#if !defined(_WIN32)
+   if (state->ctx.envp) {
+      System_FreeNativeEnviron(state->ctx.envp);
+      state->ctx.envp = NULL;
+   }
+#endif
+
+   g_object_unref(state->ctx.serviceObj);
+   state->ctx.serviceObj = NULL;
+   state->ctx.config = NULL;
+   state->ctx.mainLoop = NULL;
+}
+
+
 /**
  * Loads the debug library and calls its initialization function. This function
  * panics is something goes wrong.
@@ -88,49 +132,59 @@ ToolsCoreConfFileCb(gpointer clientData)
 }
 
 
-/**
- * Cleans up the main loop after it has executed. After this function
- * returns, the fields of the state object shouldn't be used anymore.
+/*
+ ******************************************************************************
+ * ToolsCoreRunLoop --                                                  */ /**
+ *
+ * Loads and registers all plugins, and runs the service's main loop.
  *
  * @param[in]  state       Service state.
+ *
+ * @return Exit code.
+ *
+ ******************************************************************************
  */
 
-void
-ToolsCore_Cleanup(ToolsServiceState *state)
+static int
+ToolsCoreRunLoop(ToolsServiceState *state)
 {
-   ToolsCore_UnloadPlugins(state);
-   if (state->ctx.rpc != NULL) {
-      RpcChannel_Destroy(state->ctx.rpc);
-      state->ctx.rpc = NULL;
+   if (ToolsCore_GetTcloName(state) != NULL && !ToolsCore_InitRpc(state)) {
+      return 1;
    }
-   g_key_file_free(state->ctx.config);
-   g_main_loop_unref(state->ctx.mainLoop);
 
-#if defined(G_PLATFORM_WIN32)
-   if (state->ctx.comInitialized) {
-      CoUninitialize();
-      state->ctx.comInitialized = FALSE;
+   /*
+    * Start the RPC channel if it's been created. The channel may be NULL if this is
+    * not running in the context of a VM.
+    */
+   if (state->ctx.rpc && !RpcChannel_Start(state->ctx.rpc)) {
+      return 1;
    }
-#endif
 
-   if (state->debugData != NULL) {
-      state->debugData->shutdown(&state->ctx, state->debugData);
-      g_module_close(state->debugLib);
-      state->debugData = NULL;
-      state->debugLib = NULL;
+   if (!ToolsCore_LoadPlugins(state)) {
+      return 1;
    }
 
-#if !defined(_WIN32)
-   if (state->ctx.envp) {
-      System_FreeNativeEnviron(state->ctx.envp);
-      state->ctx.envp = NULL;
+   /*
+    * If not in a VM then there's no point in trying to run the loop, just exit
+    * with a '0' return status (see bug 297528 for why '0'). If we ever want
+    * to run vmtoolsd on physical hardware (or another hypervisor), we'll have
+    * to revisit this code.
+    */
+   if (!state->ctx.isVMware) {
+      return 0;
    }
+
+   ToolsCore_RegisterPlugins(state);
+   g_timeout_add(CONF_POLL_TIME * 10, ToolsCoreConfFileCb, state);
+
+#if defined(__APPLE__)
+   ToolsCore_CFRunLoop(state);
+#else
+   g_main_loop_run(state->ctx.mainLoop);
 #endif
 
-   g_object_unref(state->ctx.serviceObj);
-   state->ctx.serviceObj = NULL;
-   state->ctx.config = NULL;
-   state->ctx.mainLoop = NULL;
+   ToolsCoreCleanup(state);
+   return state->ctx.errorCode;
 }
 
 
@@ -248,11 +302,9 @@ ToolsCore_ReloadConfig(ToolsServiceState *state,
  * Performs any initial setup steps for the service's main loop.
  *
  * @param[in]  state       Service state.
- *
- * @return Whether initialization was successful.
  */
 
-gboolean
+void
 ToolsCore_Setup(ToolsServiceState *state)
 {
    GMainContext *gctx;
@@ -278,40 +330,6 @@ ToolsCore_Setup(ToolsServiceState *state)
    if (state->debugPlugin != NULL) {
       ToolsCoreInitializeDebug(state);
    }
-
-   /* Initialize the RpcIn channel for the known tools services. */
-   if (ToolsCore_GetTcloName(state) != NULL &&
-       !ToolsCore_InitRpc(state)) {
-      goto error;
-   }
-
-   /*
-    * Start the RPC channel if it's been created. The channel may be NULL if this is
-    * not running in the context of a VM.
-    */
-   if (state->ctx.rpc && !RpcChannel_Start(state->ctx.rpc)) {
-      goto error;
-   }
-
-   if (!ToolsCore_LoadPlugins(state)) {
-      goto error;
-   }
-
-   ToolsCore_RegisterPlugins(state);
-   goto exit;
-
-error:
-   if (state->ctx.rpc != NULL) {
-      RpcChannel_Destroy(state->ctx.rpc);
-      state->ctx.rpc = NULL;
-   }
-   if (state->ctx.mainLoop != NULL) {
-      g_main_loop_unref(state->ctx.mainLoop);
-      state->ctx.mainLoop = NULL;
-   }
-
-exit:
-   return (state->ctx.mainLoop != NULL);
 }
 
 
@@ -326,21 +344,16 @@ exit:
 int
 ToolsCore_Run(ToolsServiceState *state)
 {
-   /*
-    * If there's no RPC channel (not in a VM) then there's no point in trying to
-    * run the loop, just exit with a '0' return status (see bug 297528 for why '0').
-    */
-   if (!state->ctx.rpc) {
-      return 0;
+   if (state->debugData != NULL) {
+      int ret = state->debugData->run(&state->ctx,
+                                      ToolsCoreRunLoop,
+                                      state,
+                                      state->debugData);
+      g_module_close(state->debugLib);
+      state->debugData = NULL;
+      state->debugLib = NULL;
+      return ret;
    }
-
-   g_timeout_add(CONF_POLL_TIME * 10, ToolsCoreConfFileCb, state);
-
-#if defined(__APPLE__)
-   ToolsCore_CFRunLoop(state);
-#else
-   g_main_loop_run(state->ctx.mainLoop);
-#endif
-   return state->ctx.errorCode;
+   return ToolsCoreRunLoop(state);
 }
 
index 83833d068c257ddf82b4b4c7669c4c44b1461938..9782c33dac46fa066cc5c8a0fc718eb66f45af13 100644 (file)
@@ -187,9 +187,7 @@ main(int argc,
       return 0;
    }
 
-   if (!ToolsCore_Setup(&gState)) {
-      goto exit;
-   }
+   ToolsCore_Setup(&gState);
 
    src = VMTools_NewSignalSource(SIGHUP);
    VMTOOLSAPP_ATTACH_SOURCE(&gState.ctx, src,
@@ -224,8 +222,6 @@ main(int argc,
 
    ret = ToolsCore_Run(&gState);
 
-   ToolsCore_Cleanup(&gState);
-
    if (gState.pidFile != NULL) {
       g_unlink(gState.pidFile);
    }
index 54942bd34eb25751ee004dfbb2edf406ad85c406..c25e836ecfa0f4d0a0e8452ed9249ff868ea7ac4 100644 (file)
@@ -99,9 +99,6 @@ ToolsCore_ParseCommandLine(ToolsServiceState *state,
                            int argc,
                            char *argv[]);
 
-void
-ToolsCore_Cleanup(ToolsServiceState *state);
-
 void
 ToolsCore_DumpPluginInfo(ToolsServiceState *state);
 
@@ -114,7 +111,7 @@ ToolsCore_GetTcloName(ToolsServiceState *state);
 int
 ToolsCore_Run(ToolsServiceState *state);
 
-gboolean
+void
 ToolsCore_Setup(ToolsServiceState *state);
 
 gboolean
index 53dc33ff0754dbaf7bc76087de6a33574f418a7f..a22934bf29598411516a6b3afe6dd4f4ed2ced9b 100644 (file)
@@ -19,6 +19,7 @@ plugindir = @TEST_PLUGIN_INSTALLDIR@
 plugin_LTLIBRARIES = libtestDebug.la
 
 libtestDebug_la_CPPFLAGS =
+libtestDebug_la_CPPFLAGS += @CUNIT_CPPFLAGS@
 libtestDebug_la_CPPFLAGS += @GOBJECT_CPPFLAGS@
 libtestDebug_la_CPPFLAGS += @PLUGIN_CPPFLAGS@
 
@@ -26,6 +27,7 @@ libtestDebug_la_LDFLAGS =
 libtestDebug_la_LDFLAGS += @PLUGIN_LDFLAGS@
 
 libtestDebug_la_LIBADD =
+libtestDebug_la_LIBADD += @CUNIT_LIBS@
 libtestDebug_la_LIBADD += @GOBJECT_LIBS@
 libtestDebug_la_LIBADD += @VMTOOLS_LIBS@
 libtestDebug_la_LIBADD += ../vmrpcdbg/libvmrpcdbg.la
index 0aa3f9e5f3e2e29f1c62b190be59ff4fbf1a27de..bb017d813e157bb0919500e043a9f72c98b686d1 100644 (file)
@@ -26,6 +26,8 @@
 
 #define G_LOG_DOMAIN "testDebug"
 #include <glib-object.h>
+#include <CUnit/CUnit.h>
+
 #include "util.h"
 #include "guestrpc/ghiGetBinaryHandlers.h"
 #include "vmware/guestrpc/tclodefs.h"
@@ -91,10 +93,8 @@ TestDebugValidateReset(RpcInData *data,
                        gboolean ret)
 {
    ToolsAppCtx *ctx = data->appCtx;
-   g_assert(data->result != NULL);
-   if (strcmp(data->result, "ATR debug") != 0) {
-      g_error("Unexpected response to reset: %s\n", data->result);
-   }
+   RPCDEBUG_ASSERT(data->result != NULL, FALSE);
+   CU_ASSERT_STRING_EQUAL(data->result, "ATR debug");
 
    /*
     * If reset was successful, connect the "test-signal" signal so we
@@ -132,12 +132,11 @@ TestDebugReceiveRpc1(char *data,
 {
    GHIBinaryHandlersIconDetails *details = (GHIBinaryHandlersIconDetails *) data;
 
-   g_assert(gSignalReceived);
-   g_assert(details->width == 100);
-   g_assert(details->height == 200);
-   g_assert(strcmp(details->identifier, "rpc1test") == 0);
+   CU_ASSERT(gSignalReceived);
+   CU_ASSERT(details->width == 100);
+   CU_ASSERT(details->height == 200);
+   CU_ASSERT_STRING_EQUAL(details->identifier, "rpc1test");
 
-   g_debug("Successfully validated rpc1!\n");
    return TRUE;
 }
 
@@ -179,7 +178,7 @@ static gboolean
 TestDebugValidateUnknown(RpcInData *data,
                          gboolean ret)
 {
-   g_assert(strcmp(data->result, "Unknown Command") == 0);
+   CU_ASSERT_STRING_EQUAL(data->result, "Unknown Command");
    return !ret;
 }
 
index dbb6e76a03d444efbcfefeecd2298f0c4fa7836e..44824c442e54ceb986c9f6c438a5bab295bb6b55 100644 (file)
@@ -19,6 +19,7 @@ plugindir = @TEST_PLUGIN_INSTALLDIR@
 plugin_LTLIBRARIES = libtestPlugin.la
 
 libtestPlugin_la_CPPFLAGS =
+libtestPlugin_la_CPPFLAGS += @CUNIT_CPPFLAGS@
 libtestPlugin_la_CPPFLAGS += @GOBJECT_CPPFLAGS@
 libtestPlugin_la_CPPFLAGS += @PLUGIN_CPPFLAGS@
 
@@ -26,6 +27,7 @@ libtestPlugin_la_LDFLAGS =
 libtestPlugin_la_LDFLAGS += @PLUGIN_LDFLAGS@
 
 libtestPlugin_la_LIBADD =
+libtestPlugin_la_LIBADD += @CUNIT_LIBS@
 libtestPlugin_la_LIBADD += @GOBJECT_LIBS@
 libtestPlugin_la_LIBADD += @VMTOOLS_LIBS@
 libtestPlugin_la_LIBADD += @XDR_LIBS@
index 7c0ac6441107a56e1f0b2cf4ac3a88a32206d11b..ca70419953a9e53e23489976b63011138844aa25 100644 (file)
 
 #include <glib-object.h>
 #include <gmodule.h>
+#include <CUnit/CUnit.h>
+
 #include "testData.h"
 #include "util.h"
 #include "guestrpc/ghiGetBinaryHandlers.h"
 #include "vmware/tools/plugin.h"
+#include "vmware/tools/rpcdebug.h"
 #include "vmware/tools/utils.h"
 
 #define TEST_APP_PROVIDER        "TestProvider"
@@ -72,9 +75,9 @@ TestPluginRpc1(RpcInData *data)
    char *cmd;
    size_t cmdLen;
 
-   g_assert(details->width == 100);
-   g_assert(details->height == 200);
-   g_assert(strcmp(details->identifier, "rpc1test") == 0);
+   CU_ASSERT_EQUAL(details->width, 100);
+   CU_ASSERT_EQUAL(details->height, 200);
+   CU_ASSERT_STRING_EQUAL(details->identifier, "rpc1test");
 
    g_signal_emit_by_name(ctx->serviceObj, "test-signal");
 
@@ -185,7 +188,7 @@ TestPluginReset(gpointer src,
                 ToolsAppCtx *ctx,
                 ToolsPluginData *plugin)
 {
-   g_assert(ctx != NULL);
+   RPCDEBUG_ASSERT(ctx != NULL, FALSE);
    g_debug("%s: reset signal for app %s\n", __FUNCTION__, ctx->name);
    return TRUE;
 }
@@ -238,10 +241,10 @@ TestPluginShutdown(gpointer src,
                    ToolsPluginData *plugin)
 {
    g_debug("%s: shutdown signal.\n", __FUNCTION__);
-   ASSERT(gInvalidSigError);
-   ASSERT(gInvalidAppError);
-   ASSERT(gInvalidAppProvider);
-   ASSERT(gValidAppRegistration);
+   CU_ASSERT(gInvalidSigError);
+   CU_ASSERT(gInvalidAppError);
+   CU_ASSERT(gInvalidAppProvider);
+   CU_ASSERT(gValidAppRegistration);
 }
 
 
@@ -290,7 +293,7 @@ TestProviderRegisterApp(ToolsAppCtx *ctx,
    TestApp *app = reg;
    g_debug("%s: registration data is '%s'\n", __FUNCTION__, app->name);
    gValidAppRegistration |= strcmp(app->name, TEST_APP_NAME) == 0;
-   ASSERT(strcmp(app->name, TEST_APP_DONT_REGISTER) != 0);
+   CU_ASSERT(strcmp(app->name, TEST_APP_DONT_REGISTER) != 0);
    return (strcmp(app->name, TEST_APP_ERROR) != 0);
 }
 
@@ -313,23 +316,21 @@ TestPluginErrorCb(ToolsAppCtx *ctx,
    /* Make sure the non-existant signal we tried to register fires an error. */
    if (type == TOOLS_APP_SIGNALS) {
       ToolsPluginSignalCb *sig = data;
-      ASSERT(strcmp(sig->signame, TEST_SIG_INVALID) == 0);
-      (void) sig;
+      CU_ASSERT(strcmp(sig->signame, TEST_SIG_INVALID) == 0);
       gInvalidSigError = TRUE;
    }
 
    /* Make sure we're notified about the "error" app we tried to register. */
    if (type == 42) {
       TestApp *app = data;
-      ASSERT(strcmp(app->name, TEST_APP_ERROR) == 0);
-      (void) app;
+      CU_ASSERT(strcmp(app->name, TEST_APP_ERROR) == 0);
       gInvalidAppError = TRUE;
       return FALSE;
    }
 
    /* Make sure we're notified about a non-existant app provider. */
    if (type == 43) {
-      ASSERT(data == NULL);
+      CU_ASSERT(data == NULL);
       gInvalidAppProvider = TRUE;
    }
 
index 3fa481de0b3b162d077338a60a06353f3189c0b7..8d5f2e5b0aef26fddc40ca2750da0bb8cff649f3 100644 (file)
@@ -18,6 +18,7 @@
 noinst_LTLIBRARIES = libvmrpcdbg.la
 
 libvmrpcdbg_la_CPPFLAGS =
+libvmrpcdbg_la_CPPFLAGS += @CUNIT_CPPFLAGS@
 libvmrpcdbg_la_CPPFLAGS += @GMODULE_CPPFLAGS@
 libvmrpcdbg_la_CPPFLAGS += @VMTOOLS_CPPFLAGS@
 
@@ -25,6 +26,7 @@ libvmrpcdbg_la_LDFLAGS =
 libvmrpcdbg_la_LDFLAGS += @PLUGIN_LDFLAGS@
 
 libvmrpcdbg_la_LIBADD =
+libvmrpcdbg_la_LIBADD += @CUNIT_LIBS@
 libvmrpcdbg_la_LIBADD += @GMODULE_LIBS@
 libvmrpcdbg_la_LIBADD += @VMTOOLS_LIBS@
 libvmrpcdbg_la_LIBADD += @XDR_LIBS@
index 94947509a4d20e712409588d7d7a0dc55331a335..a099736cc05af7e24592e69dbee95fe11055a617 100644 (file)
@@ -31,9 +31,9 @@
 
 #include "strutil.h"
 #include "util.h"
+#include "vmrpcdbgInt.h"
 #include "vmxrpc.h"
 #include "xdrutil.h"
-#include "vmware/tools/rpcdebug.h"
 #include "vmware/tools/utils.h"
 
 typedef struct DbgChannelData {
@@ -184,7 +184,7 @@ RpcDebugSend(RpcChannel *chan,
    RpcDebugRecvFn recvFn = NULL;
    gboolean ret = TRUE;
 
-   g_assert(chan->appName != NULL);
+   ASSERT(chan->appName != NULL);
 
    /* Be paranoid. Like the VMX, NULL-terminate the incoming data. */
    copy = g_malloc(dataLen + 1);
@@ -214,7 +214,7 @@ RpcDebugSend(RpcChannel *chan,
       if (mapping->xdrProc != NULL) {
          char *start;
 
-         g_assert(mapping->xdrSize > 0);
+         ASSERT(mapping->xdrSize > 0);
 
          /* Find out where the XDR data starts. */
          start = strchr(copy, ' ');
@@ -265,7 +265,7 @@ static void
 RpcDebugShutdown(RpcChannel *chan)
 {
    DbgChannelData *cdata = chan->_private;
-   g_assert(chan->appName != NULL);
+   ASSERT(chan->appName != NULL);
    if (cdata->hasLibRef) {
       RpcDebug_DecRef(chan->appCtx);
    }
@@ -292,7 +292,7 @@ RpcDebug_NewDebugChannel(ToolsAppCtx *ctx,
    DbgChannelData *cdata;
    RpcChannel *ret;
 
-   g_assert(data != NULL);
+   ASSERT(data != NULL);
 
    ret = g_malloc0(sizeof *ret);
    ret->start = RpcDebugStart;
index efe5655eaef2b875cf382df998c96deda8e6e88c..8504fb70c63bbeef3bf6331ac6bfec98e039c573 100644 (file)
 #define G_LOG_DOMAIN "rpcdbg"
 
 #include <gmodule.h>
-#include <rpc/rpc.h>
+#include "CUnit/Basic.h"
+#include <CUnit/CUnit.h>
+
 #include "util.h"
-#include "vmware/tools/rpcdebug.h"
+#include "vmrpcdbgInt.h"
 
-#if !defined(__APPLE__)
 #include "embed_version.h"
 #include "vmtoolsd_version.h"
 VM_EMBED_VERSION(VMTOOLSD_VERSION_STRING);
-#endif
 
 static GModule *gPlugin = NULL;
 
@@ -45,6 +45,98 @@ static gint gRefCount = 0;
 #endif
 
 
+/*
+ * Static variables to hold the app's main loop data. CUnit test functions
+ * don't take any parameters so there's no other way to do this...
+ */
+static void (*gRunMainLoop)(gpointer);
+static gpointer gRunData;
+
+
+/*
+ ******************************************************************************
+ * RpcDebugRunLoop --                                                   */ /**
+ *
+ * Runs the app's main loop as part of a CUnit test.
+ *
+ ******************************************************************************
+ */
+
+static void
+RpcDebugRunLoop(void)
+{
+   ASSERT(gRunMainLoop);
+   ASSERT(gRunData);
+   gRunMainLoop(gRunData);
+}
+
+
+/*
+ ******************************************************************************
+ * RpcDebugRun --                                                       */ /**
+ *
+ * Runs the main application's main loop function through CUnit so that we
+ * get all the test tracking / reporting goodness that it provides.
+ *
+ * @param[in] runMainLoop     A function that runs the application's main loop.
+ *                            The function should take one argument,
+ * @param[in] runData         Argument to be passed to the main loop function.
+ * @param[in] ldata           Debug library data.
+ *
+ * @return CUnit test run result (cast to int).
+ *
+ ******************************************************************************
+ */
+
+static int
+RpcDebugRun(ToolsAppCtx *ctx,
+            gpointer runMainLoop,
+            gpointer runData,
+            RpcDebugLibData *ldata)
+{
+   CU_ErrorCode err;
+   CU_Suite *suite;
+   CU_Test *test;
+
+   ASSERT(runMainLoop != NULL);
+   ASSERT(ldata != NULL);
+
+   err = CU_initialize_registry();
+   ASSERT(err == CUE_SUCCESS);
+
+   suite = CU_add_suite(g_module_name(gPlugin), NULL, NULL);
+   ASSERT(suite != NULL);
+
+   test = CU_add_test(suite, g_module_name(gPlugin), RpcDebugRunLoop);
+   ASSERT(test != NULL);
+
+   gRunMainLoop = runMainLoop;
+   gRunData = runData;
+
+   err = CU_basic_run_tests();
+
+   /* Clean up internal library / debug plugin state. */
+   ASSERT(g_atomic_int_get(&gRefCount) == 0);
+   ASSERT(ldata != NULL);
+
+   if (ldata->debugPlugin->shutdownFn != NULL) {
+      ldata->debugPlugin->shutdownFn(ctx, ldata->debugPlugin);
+   }
+
+   if (gPlugin != NULL) {
+      g_module_close(gPlugin);
+      gPlugin = NULL;
+   }
+
+   if (CU_get_failure_list() != NULL) {
+      err = 1;
+   }
+
+   CU_cleanup_registry();
+   return (int) err;
+}
+
+
 /**
  * Decreases the internal ref count of the library. When the ref count reaches
  * zero, this function will ask the application's main loop to stop running.
@@ -90,9 +182,10 @@ RpcDebug_Initialize(ToolsAppCtx *ctx,
    RpcDebugOnLoadFn onload;
    RpcDebugLibData *ldata;
 
+   ASSERT(gPlugin == NULL);
+
    ldata = g_malloc(sizeof *ldata);
 
-   g_assert(gPlugin == NULL);
    gPlugin = g_module_open(dbgPlugin, G_MODULE_BIND_LOCAL);
    if (gPlugin == NULL) {
       g_error("Can't load plugin: %s\n", dbgPlugin);
@@ -108,7 +201,7 @@ RpcDebug_Initialize(ToolsAppCtx *ctx,
    }
 
    ldata->newDebugChannel = RpcDebug_NewDebugChannel;
-   ldata->shutdown = RpcDebug_Shutdown;
+   ldata->run = RpcDebugRun;
 
    return ldata;
 }
@@ -161,28 +254,3 @@ RpcDebug_SetResult(const char *str,
    }
 }
 
-
-/**
- * Shuts down the debug library. Unloads the debug plugin. The plugin's data
- * shouldn't be used after this function is called.
- *
- * @param[in]  ctx      The application context.
- * @param[in]  ldata    Debug library data.
- */
-
-void
-RpcDebug_Shutdown(ToolsAppCtx *ctx,
-                  RpcDebugLibData *ldata)
-{
-   g_assert(g_atomic_int_get(&gRefCount) == 0);
-   g_assert(ldata != NULL);
-
-   if (ldata->debugPlugin != NULL && ldata->debugPlugin->shutdownFn != NULL) {
-      ldata->debugPlugin->shutdownFn(ctx, ldata->debugPlugin);
-   }
-   if (gPlugin != NULL) {
-      g_module_close(gPlugin);
-      gPlugin = NULL;
-   }
-}
-
diff --git a/open-vm-tools/tests/vmrpcdbg/vmrpcdbgInt.h b/open-vm-tools/tests/vmrpcdbg/vmrpcdbgInt.h
new file mode 100644 (file)
index 0000000..de12f89
--- /dev/null
@@ -0,0 +1,35 @@
+/*********************************************************
+ * Copyright (C) 2009 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no 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 Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
+ *
+ *********************************************************/
+
+#ifndef _VMRPCDBGINT_H_
+#define _VMRPCDBGINT_H_
+
+/**
+ * @file vmrpcdbgInt.h
+ *
+ * Internal definitions for the vmrpcdbg library.
+ */
+
+#include "vmware/tools/rpcdebug.h"
+
+RpcChannel *
+RpcDebug_NewDebugChannel(ToolsAppCtx *ctx,
+                         RpcDebugLibData *data);
+
+#endif /* _VMRPCDBGINT_H_ */
+