From: VMware, Inc <> Date: Wed, 20 Jan 2010 21:27:24 +0000 (-0800) Subject: Rework the vmrpcdbg library to use CUnit. X-Git-Tag: 2010.01.19-226760~34 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c751e2500b022b5ba762d834fec3dcf7be734446;p=thirdparty%2Fopen-vm-tools.git Rework the vmrpcdbg library to use CUnit. 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 --- diff --git a/open-vm-tools/Makefile.am b/open-vm-tools/Makefile.am index d9d7da3c9..7ab65fc92 100644 --- a/open-vm-tools/Makefile.am +++ b/open-vm-tools/Makefile.am @@ -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 diff --git a/open-vm-tools/configure.ac b/open-vm-tools/configure.ac index 43e1cbbfd..264e5e759 100644 --- a/open-vm-tools/configure.ac +++ b/open-vm-tools/configure.ac @@ -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") diff --git a/open-vm-tools/lib/include/vmware/tools/rpcdebug.h b/open-vm-tools/lib/include/vmware/tools/rpcdebug.h index 3e00ce17d..04f2c9b44 100644 --- a/open-vm-tools/lib/include/vmware/tools/rpcdebug.h +++ b/open-vm-tools/lib/include/vmware/tools/rpcdebug.h @@ -31,6 +31,19 @@ #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 /** @} */ diff --git a/open-vm-tools/services/vmtoolsd/mainLoop.c b/open-vm-tools/services/vmtoolsd/mainLoop.c index 476e65729..0a039f6f4 100644 --- a/open-vm-tools/services/vmtoolsd/mainLoop.c +++ b/open-vm-tools/services/vmtoolsd/mainLoop.c @@ -40,6 +40,50 @@ #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); } diff --git a/open-vm-tools/services/vmtoolsd/mainPosix.c b/open-vm-tools/services/vmtoolsd/mainPosix.c index 83833d068..9782c33da 100644 --- a/open-vm-tools/services/vmtoolsd/mainPosix.c +++ b/open-vm-tools/services/vmtoolsd/mainPosix.c @@ -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); } diff --git a/open-vm-tools/services/vmtoolsd/toolsCoreInt.h b/open-vm-tools/services/vmtoolsd/toolsCoreInt.h index 54942bd34..c25e836ec 100644 --- a/open-vm-tools/services/vmtoolsd/toolsCoreInt.h +++ b/open-vm-tools/services/vmtoolsd/toolsCoreInt.h @@ -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 diff --git a/open-vm-tools/tests/testDebug/Makefile.am b/open-vm-tools/tests/testDebug/Makefile.am index 53dc33ff0..a22934bf2 100644 --- a/open-vm-tools/tests/testDebug/Makefile.am +++ b/open-vm-tools/tests/testDebug/Makefile.am @@ -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 diff --git a/open-vm-tools/tests/testDebug/testDebug.c b/open-vm-tools/tests/testDebug/testDebug.c index 0aa3f9e5f..bb017d813 100644 --- a/open-vm-tools/tests/testDebug/testDebug.c +++ b/open-vm-tools/tests/testDebug/testDebug.c @@ -26,6 +26,8 @@ #define G_LOG_DOMAIN "testDebug" #include +#include + #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; } diff --git a/open-vm-tools/tests/testPlugin/Makefile.am b/open-vm-tools/tests/testPlugin/Makefile.am index dbb6e76a0..44824c442 100644 --- a/open-vm-tools/tests/testPlugin/Makefile.am +++ b/open-vm-tools/tests/testPlugin/Makefile.am @@ -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@ diff --git a/open-vm-tools/tests/testPlugin/testPlugin.c b/open-vm-tools/tests/testPlugin/testPlugin.c index 7c0ac6441..ca7041995 100644 --- a/open-vm-tools/tests/testPlugin/testPlugin.c +++ b/open-vm-tools/tests/testPlugin/testPlugin.c @@ -28,10 +28,13 @@ #include #include +#include + #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; } diff --git a/open-vm-tools/tests/vmrpcdbg/Makefile.am b/open-vm-tools/tests/vmrpcdbg/Makefile.am index 3fa481de0..8d5f2e5b0 100644 --- a/open-vm-tools/tests/vmrpcdbg/Makefile.am +++ b/open-vm-tools/tests/vmrpcdbg/Makefile.am @@ -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@ diff --git a/open-vm-tools/tests/vmrpcdbg/debugChannel.c b/open-vm-tools/tests/vmrpcdbg/debugChannel.c index 94947509a..a099736cc 100644 --- a/open-vm-tools/tests/vmrpcdbg/debugChannel.c +++ b/open-vm-tools/tests/vmrpcdbg/debugChannel.c @@ -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; diff --git a/open-vm-tools/tests/vmrpcdbg/vmrpcdbg.c b/open-vm-tools/tests/vmrpcdbg/vmrpcdbg.c index efe5655ea..8504fb70c 100644 --- a/open-vm-tools/tests/vmrpcdbg/vmrpcdbg.c +++ b/open-vm-tools/tests/vmrpcdbg/vmrpcdbg.c @@ -25,15 +25,15 @@ #define G_LOG_DOMAIN "rpcdbg" #include -#include +#include "CUnit/Basic.h" +#include + #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 index 000000000..de12f895d --- /dev/null +++ b/open-vm-tools/tests/vmrpcdbg/vmrpcdbgInt.h @@ -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_ */ +