/* $Id: tstRTLocalIpc.cpp 47168 2013-07-15 14:53:55Z vboxsync $ */ /** @file * IPRT Testcase - RTLocalIpc. */ /* * Copyright (C) 2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. * * The contents of this file may alternatively be used under the terms * of the Common Development and Distribution License Version 1.0 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the * VirtualBox OSE distribution, in which case the provisions of the * CDDL are applicable instead of those of the GPL. * * You may elect to license modified versions of this file under the * terms and conditions of either the GPL or the CDDL or both. */ /******************************************************************************* * Header Files * *******************************************************************************/ #include #include #include #include #include #include #include #include #include typedef struct LOCALIPCTHREADCTX { /** The IPC server handle. */ RTLOCALIPCSERVER hServer; /** The test handle. */ RTTEST hTest; } LOCALIPCTHREADCTX, *PLOCALIPCTHREADCTX; static int testServerListenAndCancel2(const char *pszExecPath) { const char *apszArgs[4] = { pszExecPath, "child", "testServerListenAndCancel", NULL }; RTPROCESS hProc; int rc = RTProcCreate(pszExecPath, apszArgs, RTENV_DEFAULT, 0 /* fFlags*/, &hProc); return rc; } static DECLCALLBACK(int) testServerListenAndCancelThread(RTTHREAD hSelf, void *pvUser) { PRTLOCALIPCSERVER pServer = (PRTLOCALIPCSERVER)pvUser; AssertPtr(pServer); RTThreadSleep(5000); /* Wait a bit to simulate waiting in main thread. */ int rc = RTLocalIpcServerCancel(*pServer); AssertRC(rc); return 0; } static int testServerListenAndCancel(RTTEST hTest, const char *pszExecPath) { RTTestSub(hTest, "testServerListenAndCancel"); RTLOCALIPCSERVER ipcServer; int rc = RTLocalIpcServerCreate(&ipcServer, "testServerListenAndCancel", RTLOCALIPC_FLAGS_MULTI_SESSION); if (RT_SUCCESS(rc)) { /* Spawn a simple worker thread and let it listen for incoming connections. * In the meanwhile we try to cancel the server and see what happens. */ RTTHREAD hThread; rc = RTThreadCreate(&hThread, testServerListenAndCancelThread, &ipcServer, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc1"); if (RT_SUCCESS(rc)) { do { RTTestPrintf(hTest, RTTESTLVL_INFO, "Listening for incoming connections ...\n"); RTLOCALIPCSESSION ipcSession; RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerListen(ipcServer, &ipcSession), VERR_CANCELLED); RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerCancel(ipcServer), VINF_SUCCESS); RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerDestroy(ipcServer), VINF_SUCCESS); RTTestPrintf(hTest, RTTESTLVL_INFO, "Waiting for thread to exit ...\n"); RTTEST_CHECK_RC(hTest, RTThreadWait(hThread, 30 * 1000 /* 30s timeout */, NULL), VINF_SUCCESS); } while (0); } else RTTestIFailed("Unable to create thread for cancelling server, rc=%Rrc\n", rc); } else RTTestIFailed("Unable to create IPC server, rc=%Rrc\n", rc); return VINF_SUCCESS; } static DECLCALLBACK(int) testSessionConnectionThread(RTTHREAD hSelf, void *pvUser) { PLOCALIPCTHREADCTX pCtx = (PLOCALIPCTHREADCTX)pvUser; AssertPtr(pCtx); int rc; RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionConnectionThread: Listening for incoming connections ...\n"); for (;;) { RTLOCALIPCSESSION ipcSession; rc = RTLocalIpcServerListen(pCtx->hServer, &ipcSession); RTTestPrintf(pCtx->hTest, RTTESTLVL_DEBUG, "testSessionConnectionThread: Listening returned with rc=%Rrc\n", rc); if (RT_SUCCESS(rc)) { RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionConnectionThread: Got new client connection\n"); } else break; } RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionConnectionThread: Ended with rc=%Rrc\n", rc); return rc; } static RTEXITCODE testSessionConnectionChild(int argc, char **argv, RTTEST hTest) { do { RTThreadSleep(2000); /* Fudge */ RTLOCALIPCSESSION clientSession; RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionConnect(&clientSession, "tstRTLocalIpcSessionConnection", 0 /* Flags */), VINF_SUCCESS); RTThreadSleep(5000); /* Fudge */ RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionClose(clientSession), VINF_SUCCESS); } while (0); return !RTTestErrorCount(hTest) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; } static int testSessionConnection(RTTEST hTest, const char *pszExecPath) { RTTestSub(hTest, "testSessionConnection"); RTLOCALIPCSERVER ipcServer; int rc = RTLocalIpcServerCreate(&ipcServer, "tstRTLocalIpcSessionConnection", RTLOCALIPC_FLAGS_MULTI_SESSION); if (RT_SUCCESS(rc)) { #ifndef VBOX_TESTCASES_WITH_NO_THREADING LOCALIPCTHREADCTX threadCtx = { ipcServer, hTest }; /* Spawn a simple worker thread and let it listen for incoming connections. * In the meanwhile we try to cancel the server and see what happens. */ RTTHREAD hThread; rc = RTThreadCreate(&hThread, testSessionConnectionThread, &threadCtx, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc2"); if (RT_SUCCESS(rc)) { do { RTPROCESS hProc; const char *apszArgs[4] = { pszExecPath, "child", "tstRTLocalIpcSessionConnectionFork", NULL }; RTTEST_CHECK_RC_BREAK(hTest, RTProcCreate(pszExecPath, apszArgs, RTENV_DEFAULT, 0 /* fFlags*/, &hProc), VINF_SUCCESS); RTPROCSTATUS stsChild; RTTEST_CHECK_RC_BREAK(hTest, RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &stsChild), VINF_SUCCESS); RTTestPrintf(hTest, RTTESTLVL_INFO, "Child terminated, waiting for server thread ...\n"); RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerCancel(ipcServer), VINF_SUCCESS); int threadRc; RTTEST_CHECK_RC(hTest, RTThreadWait(hThread, 30 * 1000 /* 30s timeout */, &threadRc), VINF_SUCCESS); RTTEST_CHECK_RC_BREAK(hTest, threadRc, VERR_CANCELLED); RTTestPrintf(hTest, RTTESTLVL_INFO, "Server thread terminated successfully\n"); RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerDestroy(ipcServer), VINF_SUCCESS); RTTEST_CHECK_BREAK(hTest, stsChild.enmReason == RTPROCEXITREASON_NORMAL); RTTEST_CHECK_BREAK(hTest, stsChild.iStatus == 0); } while (0); } else RTTestFailed(hTest, "Unable to create thread for cancelling server, rc=%Rrc\n", rc); #else do { RTPROCESS hProc; const char *apszArgs[4] = { pszExecPath, "child", "tstRTLocalIpcSessionConnectionFork", NULL }; RTTEST_CHECK_RC_BREAK(hTest, RTProcCreate(pszExecPath, apszArgs, RTENV_DEFAULT, 0 /* fFlags*/, &hProc), VINF_SUCCESS); RTLOCALIPCSESSION ipcSession; rc = RTLocalIpcServerListen(ipcServer, &ipcSession); if (RT_SUCCESS(rc)) { RTTestPrintf(hTest, RTTESTLVL_INFO, "testSessionConnectionThread: Got new client connection\n"); } else RTTestFailed(hTest, "Error while listening, rc=%Rrc\n", rc); } while (0); #endif } else RTTestFailed(hTest, "Unable to create IPC server, rc=%Rrc\n", rc); return VINF_SUCCESS; } static DECLCALLBACK(int) testSessionWaitThread(RTTHREAD hSelf, void *pvUser) { PLOCALIPCTHREADCTX pCtx = (PLOCALIPCTHREADCTX)pvUser; AssertPtr(pCtx); int rc; for (;;) { RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionWaitThread: Listening for incoming connections ...\n"); RTLOCALIPCSESSION ipcSession; rc = RTLocalIpcServerListen(pCtx->hServer, &ipcSession); if (RT_SUCCESS(rc)) { RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionWaitThread: Got new client connection, waiting a bit ...\n"); RTThreadSleep(2000); rc = RTLocalIpcSessionClose(ipcSession); } else { RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionWaitThread: Listening ended with rc=%Rrc\n", rc); break; } } RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionWaitThread: Ended with rc=%Rrc\n", rc); return rc; } static RTEXITCODE testSessionWaitChild(int argc, char **argv, RTTEST hTest) { do { RTThreadSleep(2000); /* Fudge. */ RTLOCALIPCSESSION clientSession; RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionConnect(&clientSession, "tstRTLocalIpcSessionWait", 0 /* Flags */), VINF_SUCCESS); RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionWaitForData(clientSession, 100 /* 100ms timeout */), VERR_TIMEOUT); /* Next, try 60s timeout. Should be returning way earlier because the server closed the * connection after the first client connected. */ RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionWaitForData(clientSession, 60 * 1000), VERR_BROKEN_PIPE); /* Last try, also should fail because the server should be not around anymore. */ RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionWaitForData(clientSession, 5 * 1000), VERR_BROKEN_PIPE); RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionClose(clientSession), VINF_SUCCESS); } while (0); return !RTTestErrorCount(hTest) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; } static int testSessionWait(RTTEST hTest, const char *pszExecPath) { RTTestSub(hTest, "testSessionWait"); RTLOCALIPCSERVER ipcServer; int rc = RTLocalIpcServerCreate(&ipcServer, "tstRTLocalIpcSessionWait", RTLOCALIPC_FLAGS_MULTI_SESSION); if (RT_SUCCESS(rc)) { LOCALIPCTHREADCTX threadCtx = { ipcServer, hTest }; /* Spawn a simple worker thread and let it listen for incoming connections. * In the meanwhile we try to cancel the server and see what happens. */ RTTHREAD hThread; rc = RTThreadCreate(&hThread, testSessionWaitThread, &threadCtx, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc3"); if (RT_SUCCESS(rc)) { do { RTPROCESS hProc; const char *apszArgs[4] = { pszExecPath, "child", "tstRTLocalIpcSessionWaitFork", NULL }; RTTEST_CHECK_RC_BREAK(hTest, RTProcCreate(pszExecPath, apszArgs, RTENV_DEFAULT, 0 /* fFlags*/, &hProc), VINF_SUCCESS); RTThreadSleep(5000); /* Let the server run for some time ... */ RTTestPrintf(hTest, RTTESTLVL_INFO, "Cancelling server listening\n"); RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerCancel(ipcServer), VINF_SUCCESS); /* Wait for the server thread to terminate. */ int threadRc; RTTEST_CHECK_RC(hTest, RTThreadWait(hThread, 30 * 1000 /* 30s timeout */, &threadRc), VINF_SUCCESS); RTTEST_CHECK_RC_BREAK(hTest, threadRc, VERR_CANCELLED); RTTEST_CHECK_RC(hTest, RTLocalIpcServerDestroy(ipcServer), VINF_SUCCESS); RTTestPrintf(hTest, RTTESTLVL_INFO, "Server thread terminated successfully\n"); /* Check if the child ran successfully. */ RTPROCSTATUS stsChild; RTTEST_CHECK_RC_BREAK(hTest, RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &stsChild), VINF_SUCCESS); RTTestPrintf(hTest, RTTESTLVL_INFO, "Child terminated\n"); RTTEST_CHECK_BREAK(hTest, stsChild.enmReason == RTPROCEXITREASON_NORMAL); RTTEST_CHECK_BREAK(hTest, stsChild.iStatus == 0); } while (0); } else RTTestFailed(hTest, "Unable to create thread for cancelling server, rc=%Rrc\n", rc); } else RTTestFailed(hTest, "Unable to create IPC server, rc=%Rrc\n", rc); return VINF_SUCCESS; } /** * Simple structure holding the test IPC messages. */ typedef struct LOCALIPCTESTMSG { /** The actual message. */ char szOp[255]; } LOCALIPCTESTMSG, *PLOCALIPCTESTMSG; static DECLCALLBACK(int) testSessionDataThread(RTTHREAD hSelf, void *pvUser) { PLOCALIPCTHREADCTX pCtx = (PLOCALIPCTHREADCTX)pvUser; AssertPtr(pCtx); do { /* Note: At the moment we only support one client per run. */ RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionDataThread: Listening for incoming connections ...\n"); RTLOCALIPCSESSION ipcSession; RTTEST_CHECK_RC_BREAK(pCtx->hTest, RTLocalIpcServerListen(pCtx->hServer, &ipcSession), VINF_SUCCESS); RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionDataThread: Got new client connection\n"); uint32_t cRounds = 256; /** @todo Use RTRand(). */ RTTEST_CHECK_RC_BREAK(pCtx->hTest, RTLocalIpcSessionWrite(ipcSession, &cRounds, sizeof(cRounds)), VINF_SUCCESS); RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionDataThread: Written number of rounds\n"); for (uint32_t i = 0; i < cRounds; i++) { LOCALIPCTESTMSG msg; RTTEST_CHECK_BREAK(pCtx->hTest, RTStrPrintf(msg.szOp, sizeof(msg.szOp), "YayIGotRound%RU32FromTheServer", i) > 0); RTTEST_CHECK_RC_BREAK(pCtx->hTest, RTLocalIpcSessionWrite(ipcSession, &msg, sizeof(msg)), VINF_SUCCESS); } RTThreadSleep(10 * 1000); /* Fudge. */ RTTEST_CHECK_RC_BREAK(pCtx->hTest, RTLocalIpcSessionClose(ipcSession), VINF_SUCCESS); RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionDataThread: Data successfully written\n"); } while (0); return !RTTestErrorCount(pCtx->hTest) ? VINF_SUCCESS : VERR_GENERAL_FAILURE /* Doesn't matter */; } static RTEXITCODE testSessionDataChild(int argc, char **argv, RTTEST hTest) { uint8_t *pvScratchBuf = (uint8_t*)RTMemAlloc(_1K); RTTEST_CHECK_RET(hTest, pvScratchBuf != NULL, RTEXITCODE_FAILURE); do { RTThreadSleep(2000); /* Fudge. */ RTLOCALIPCSESSION clientSession; RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionConnect(&clientSession, "tstRTLocalIpcSessionData", 0 /* Flags */), VINF_SUCCESS); /* Get number of rounds we want to read/write. */ uint32_t cRounds = 0; size_t cbRead; RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionWaitForData(clientSession, RT_INDEFINITE_WAIT), VINF_SUCCESS); RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionRead(clientSession, &cRounds, sizeof(cRounds), NULL /* Get exactly sizeof(cRounds) bytes */), VINF_SUCCESS); RTTEST_CHECK_BREAK(hTest, cRounds == 256); /** @todo Check for != 0 when using RTRand(). */ /* Process all rounds. */ size_t uOffScratchBuf = 0; char szStr[32]; for (uint32_t i = 0; i < 1; cRounds++) { RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionWaitForData(clientSession, RT_INDEFINITE_WAIT), VINF_SUCCESS); RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionRead(clientSession, pvScratchBuf, sizeof(*pvScratchBuf) - uOffScratchBuf, &cbRead), VINF_SUCCESS); uOffScratchBuf += cbRead; RTTEST_CHECK_BREAK(hTest, uOffScratchBuf <= sizeof(*pvScratchBuf)); if (uOffScratchBuf >= sizeof(LOCALIPCTESTMSG)) /* Got a complete test message? */ { PLOCALIPCTESTMSG pMsg = (PLOCALIPCTESTMSG)pvScratchBuf; RTTEST_CHECK_BREAK(hTest, pMsg != NULL); RTTEST_CHECK_BREAK(hTest, RTStrPrintf(szStr, sizeof(szStr), "YayIGotRound%RU32FromTheServer", i) > 0); RTTEST_CHECK_BREAK(hTest, !RTStrICmp(pMsg->szOp, szStr)); memcpy(pvScratchBuf, (void*)pvScratchBuf[sizeof(LOCALIPCTESTMSG)], cbRead); } if (RTTestErrorCount(hTest)) break; } RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionClose(clientSession), VINF_SUCCESS); } while (0); RTMemFree(pvScratchBuf); return !RTTestErrorCount(hTest) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; } static int testSessionData(RTTEST hTest, const char *pszExecPath) { RTTestSub(hTest, "testSessionData"); RTLOCALIPCSERVER ipcServer; int rc = RTLocalIpcServerCreate(&ipcServer, "tstRTLocalIpcSessionData", RTLOCALIPC_FLAGS_MULTI_SESSION); if (RT_SUCCESS(rc)) { LOCALIPCTHREADCTX threadCtx = { ipcServer, hTest }; /* Spawn a simple worker thread and let it listen for incoming connections. * In the meanwhile we try to cancel the server and see what happens. */ RTTHREAD hThread; rc = RTThreadCreate(&hThread, testSessionDataThread, &threadCtx, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc4"); if (RT_SUCCESS(rc)) { do { RTPROCESS hProc; const char *apszArgs[4] = { pszExecPath, "child", "tstRTLocalIpcSessionDataFork", NULL }; RTTEST_CHECK_RC_BREAK(hTest, RTProcCreate(pszExecPath, apszArgs, RTENV_DEFAULT, 0 /* fFlags*/, &hProc), VINF_SUCCESS); /* Wait for the server thread to terminate. */ int threadRc; RTTEST_CHECK_RC(hTest, RTThreadWait(hThread, 5 * 60 * 1000 /* 5 minutes timeout */, &threadRc), VINF_SUCCESS); RTTEST_CHECK_RC_BREAK(hTest, threadRc, VINF_SUCCESS); RTTEST_CHECK_RC(hTest, RTLocalIpcServerDestroy(ipcServer), VINF_SUCCESS); RTTestPrintf(hTest, RTTESTLVL_INFO, "Server thread terminated successfully\n"); /* Check if the child ran successfully. */ RTPROCSTATUS stsChild; RTTEST_CHECK_RC_BREAK(hTest, RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &stsChild), VINF_SUCCESS); RTTestPrintf(hTest, RTTESTLVL_INFO, "Child terminated\n"); RTTEST_CHECK_BREAK(hTest, stsChild.enmReason == RTPROCEXITREASON_NORMAL); RTTEST_CHECK_BREAK(hTest, stsChild.iStatus == 0); } while (0); } else RTTestFailed(hTest, "Unable to create thread for cancelling server, rc=%Rrc\n", rc); } else RTTestFailed(hTest, "Unable to create IPC server, rc=%Rrc\n", rc); return VINF_SUCCESS; } static RTEXITCODE mainChild(int argc, char **argv) { if (argc < 3) /* Safety first. */ return RTEXITCODE_FAILURE; /* Note: We assume argv[2] always contains the actual test type to perform. */ RTTEST hTest; RTEXITCODE rcExit = RTTestInitAndCreate(argv[2], &hTest); if (rcExit) return rcExit; RTTestBanner(hTest); RTAssertSetMayPanic(false); #ifdef DEBUG_andy RTAssertSetQuiet(false); #endif if (!RTStrICmp(argv[2], "tstRTLocalIpcSessionConnectionFork")) rcExit = testSessionConnectionChild(argc, argv, hTest); else if (!RTStrICmp(argv[2], "tstRTLocalIpcSessionWaitFork")) rcExit = testSessionWaitChild(argc, argv, hTest); else if (!RTStrICmp(argv[2], "tstRTLocalIpcSessionDataFork")) rcExit = testSessionDataChild(argc, argv, hTest); return RTTestSummaryAndDestroy(hTest); } int main(int argc, char **argv) { if ( argc > 2 && !RTStrICmp(argv[1], "child")) return mainChild(argc, argv); RTTEST hTest; RTEXITCODE rcExit = RTTestInitAndCreate("tstRTLocalIpc", &hTest); if (rcExit) return rcExit; RTTestBanner(hTest); char szExecPath[RTPATH_MAX]; if (!RTProcGetExecutablePath(szExecPath, sizeof(szExecPath))) RTStrCopy(szExecPath, sizeof(szExecPath), argv[0]); RTTestISub("Basics"); RTAssertSetMayPanic(false); #ifdef DEBUG_andy RTAssertSetQuiet(false); #endif /* Server-side. */ RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(NULL, NULL, 0), VERR_INVALID_POINTER, 1); RTLOCALIPCSERVER ipcServer; RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(&ipcServer, NULL, 0), VERR_INVALID_POINTER, 1); RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(&ipcServer, "", 0), VERR_INVALID_PARAMETER, 1); RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(&ipcServer, "BasicTest", 0 /* Invalid flags */), VERR_INVALID_PARAMETER, 1); RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(&ipcServer, "BasicTest", 1234 /* Invalid flags */), VERR_INVALID_PARAMETER, 1); RTTESTI_CHECK_RC_RET(RTLocalIpcServerCancel(NULL), VERR_INVALID_HANDLE, 1); RTTESTI_CHECK_RC_RET(RTLocalIpcServerDestroy(NULL), VINF_SUCCESS, 1); /* Basic server creation / destruction. */ RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(&ipcServer, "BasicTest", RTLOCALIPC_FLAGS_MULTI_SESSION), VINF_SUCCESS, 1); RTTESTI_CHECK_RC_RET(RTLocalIpcServerCancel(ipcServer), VINF_SUCCESS, 1); RTTESTI_CHECK_RC_RET(RTLocalIpcServerDestroy(ipcServer), VINF_SUCCESS, 1); /* Client-side (per session). */ RTTESTI_CHECK_RC_RET(RTLocalIpcSessionConnect(NULL, NULL, 0), VERR_INVALID_POINTER, 1); RTLOCALIPCSESSION ipcSession; RTTESTI_CHECK_RC_RET(RTLocalIpcSessionConnect(&ipcSession, NULL, 0), VERR_INVALID_POINTER, 1); RTTESTI_CHECK_RC_RET(RTLocalIpcSessionConnect(&ipcSession, "", 0), VERR_INVALID_PARAMETER, 1); RTTESTI_CHECK_RC_RET(RTLocalIpcSessionConnect(&ipcSession, "BasicTest", 1234 /* Invalid flags */), VERR_INVALID_PARAMETER, 1); RTTESTI_CHECK_RC_RET(RTLocalIpcSessionCancel(NULL), VERR_INVALID_HANDLE, 1); RTTESTI_CHECK_RC_RET(RTLocalIpcSessionClose(NULL), VINF_SUCCESS, 1); /* Basic client creation / destruction. */ RTTESTI_CHECK_RC_RET(RTLocalIpcSessionConnect(&ipcSession, "BasicTest", 0), VERR_FILE_NOT_FOUND, 1); RTTESTI_CHECK_RC_RET(RTLocalIpcServerCancel(ipcServer), VERR_INVALID_MAGIC, 1); RTTESTI_CHECK_RC_RET(RTLocalIpcServerDestroy(ipcServer), VERR_INVALID_MAGIC, 1); if (RTTestErrorCount(hTest) == 0) { /*RTTESTI_CHECK_RC_RET(testServerListenAndCancel(hTest, szExecPath), VINF_SUCCESS, 1); RTTESTI_CHECK_RC_RET(testSessionConnection(hTest, szExecPath), VINF_SUCCESS, 1); RTTESTI_CHECK_RC_RET(testSessionWait(hTest, szExecPath), VINF_SUCCESS, 1);*/ RTTESTI_CHECK_RC_RET(testSessionData(hTest, szExecPath), VINF_SUCCESS, 1); } /* * Summary. */ return RTTestSummaryAndDestroy(hTest); }