VirtualBox

Ignore:
Timestamp:
Jan 7, 2018 6:46:08 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
120093
Message:

iprt/socket,tcp,pollset: Added RTTcpCreatePair. Implemented polling fallback for winsock 1.x. Extended tstRTPoll to cover sockets and actual waiting and receiving of events on pipe & socket events.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/testcase/tstRTPoll.cpp

    r69111 r70481  
    3333#include <iprt/err.h>
    3434#include <iprt/file.h>
     35#include <iprt/log.h>
    3536#include <iprt/mem.h>
    3637#include <iprt/pipe.h>
     38#include <iprt/socket.h>
    3739#include <iprt/string.h>
     40#include <iprt/tcp.h>
    3841#include <iprt/test.h>
     42
     43
     44/*********************************************************************************************************************************
     45*   Global Variables                                                                                                             *
     46*********************************************************************************************************************************/
     47/** What we write from the threads in test 3. */
     48static char g_szHello[] = "hello!";
     49
     50
     51static DECLCALLBACK(int) tstRTPoll3PipeWriteThread(RTTHREAD hSelf, void *pvUser)
     52{
     53    RT_NOREF_PV(hSelf);
     54    RTPIPE hPipe = (RTPIPE)pvUser;
     55    RTThreadSleep(RT_MS_1SEC);
     56    return RTPipeWriteBlocking(hPipe, g_szHello, sizeof(g_szHello) - 1, NULL);
     57}
     58
     59
     60static DECLCALLBACK(int) tstRTPoll3SockWriteThread(RTTHREAD hSelf, void *pvUser)
     61{
     62    RT_NOREF_PV(hSelf);
     63    RTSOCKET hSocket = (RTSOCKET)pvUser;
     64    RTThreadSleep(RT_MS_1SEC);
     65    return RTTcpWrite(hSocket, g_szHello, sizeof(g_szHello) - 1);
     66}
     67
     68
     69static void tstRTPoll3(void)
     70{
     71    RTTestISub("Pipe & Sockets");
     72
     73    /*
     74     * Create a set and a pair of pipes and a pair of sockets.
     75     */
     76    RTPOLLSET hSet = NIL_RTPOLLSET;
     77    RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS);
     78    RTTESTI_CHECK_RETV(hSet != NIL_RTPOLLSET);
     79
     80    RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 0);
     81    RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 0, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND);
     82
     83    RTPIPE hPipeR;
     84    RTPIPE hPipeW;
     85    RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0/*fFlags*/), VINF_SUCCESS);
     86
     87    RTSOCKET hSocketR;
     88    RTSOCKET hSocketW;
     89    RTTESTI_CHECK_RC_RETV(RTTcpCreatePair(&hSocketR, &hSocketW, 0/*fFlags*/), VINF_SUCCESS);
     90
     91    /*
     92     * Add them for error checking.  These must be added first if want we their IDs
     93     * to show up when disconnecting.
     94     */
     95    RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_ERROR, 1 /*id*/), VINF_SUCCESS);
     96    RTTESTI_CHECK_RC_RETV(RTPollSetAddSocket(hSet, hSocketR, RTPOLL_EVT_ERROR, 2 /*id*/), VINF_SUCCESS);
     97    RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 2);
     98
     99    /*
     100     * Add the read ends.  Polling should time out.
     101     */
     102    RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_READ, 11 /*id*/), VINF_SUCCESS);
     103    RTTESTI_CHECK_RC_RETV(RTPollSetAddSocket(hSet, hSocketR, RTPOLL_EVT_READ, 12 /*id*/), VINF_SUCCESS);
     104
     105    RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 4);
     106
     107    RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 11 /*id*/, NULL), VINF_SUCCESS);
     108    RTHANDLE Handle;
     109    RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 11 /*id*/, &Handle), VINF_SUCCESS);
     110    RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE);
     111    RTTESTI_CHECK(Handle.u.hPipe == hPipeR);
     112
     113    RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 12 /*id*/, NULL), VINF_SUCCESS);
     114    RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 12 /*id*/, &Handle), VINF_SUCCESS);
     115    RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_SOCKET);
     116    RTTESTI_CHECK(Handle.u.hSocket == hSocketR);
     117
     118    RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL,  NULL), VERR_TIMEOUT);
     119    RTTESTI_CHECK_RC(RTPoll(hSet, 1, NULL,  NULL), VERR_TIMEOUT);
     120
     121    /*
     122     * Add the write ends.  Should indicate that the first one is ready for writing.
     123     */
     124    RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeW, RTPOLL_EVT_WRITE, 21 /*id*/), VINF_SUCCESS);
     125    RTTESTI_CHECK_RC_RETV(RTPollSetAddSocket(hSet, hSocketW, RTPOLL_EVT_WRITE, 22 /*id*/), VINF_SUCCESS);
     126
     127    uint32_t idReady = UINT32_MAX;
     128    RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, &idReady), VINF_SUCCESS);
     129    RTTESTI_CHECK(idReady == 21 || idReady == 22);
     130
     131    /*
     132     * Remove the write ends again.
     133     */
     134    RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 21), VINF_SUCCESS);
     135    RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 22), VINF_SUCCESS);
     136    RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL,  NULL), VERR_TIMEOUT);
     137
     138    /*
     139     * Kick off a thread that writes to the socket after 1 second.
     140     * This will check that we can wait and wake up.
     141     */
     142    for (uint32_t i = 0; i < 2; i++)
     143    {
     144        RTTHREAD hThread;
     145        RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstRTPoll3SockWriteThread, hSocketW, 0,
     146                                        RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test3sock"), VINF_SUCCESS);
     147
     148        uint32_t fEvents = 0;
     149        idReady = 0;
     150        uint64_t msStart = RTTimeSystemMilliTS();
     151        RTTESTI_CHECK_RC(RTPoll(hSet, 5 * RT_MS_1SEC, &fEvents, &idReady), VINF_SUCCESS);
     152        uint32_t msElapsed = RTTimeSystemMilliTS() - msStart;
     153        RTTESTI_CHECK_MSG(msElapsed >= 250 && msElapsed < 4500, ("msElapsed=%RU64\n", msElapsed));
     154        RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ);
     155        RTTESTI_CHECK(idReady == 12);
     156
     157        RTThreadWait(hThread, 5 * RT_MS_1SEC, NULL);
     158
     159        /* Drain the socket. */
     160        char    achBuf[128];
     161        size_t  cbRead = 0;
     162        RTTESTI_CHECK_RC(RTTcpReadNB(hSocketR, achBuf, sizeof(achBuf), &cbRead), VINF_SUCCESS);
     163        RTTESTI_CHECK(cbRead == sizeof(g_szHello) - 1 && memcmp(achBuf, g_szHello, sizeof(g_szHello) - 1) == 0);
     164
     165        RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL,  NULL), VERR_TIMEOUT);
     166        RTTESTI_CHECK_RC(RTPoll(hSet, 1, NULL,  NULL), VERR_TIMEOUT);
     167    }
     168
     169    /*
     170     * Kick off a thread that writes to the pipe after 1 second.
     171     * This will check that we can wait and wake up.
     172     */
     173    for (uint32_t i = 0; i < 2; i++)
     174    {
     175        RTTHREAD hThread;
     176        RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstRTPoll3PipeWriteThread, hPipeW, 0,
     177                                        RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test3pipe"), VINF_SUCCESS);
     178
     179        uint32_t fEvents = 0;
     180        idReady = 0;
     181        uint64_t msStart = RTTimeSystemMilliTS();
     182        RTTESTI_CHECK_RC(RTPoll(hSet, 5 * RT_MS_1SEC, &fEvents, &idReady), VINF_SUCCESS);
     183        uint32_t msElapsed = RTTimeSystemMilliTS() - msStart;
     184        RTTESTI_CHECK_MSG(msElapsed >= 250 && msElapsed < 4500, ("msElapsed=%RU64\n", msElapsed));
     185        RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ);
     186        RTTESTI_CHECK(idReady == 11);
     187
     188        RTThreadWait(hThread, 5 * RT_MS_1SEC, NULL);
     189
     190        /* Drain the socket. */
     191        char    achBuf[128];
     192        size_t  cbRead = 0;
     193        RTTESTI_CHECK_RC(RTPipeRead(hPipeR, achBuf, sizeof(achBuf), &cbRead), VINF_SUCCESS);
     194        RTTESTI_CHECK(cbRead == sizeof(g_szHello) - 1 && memcmp(achBuf, g_szHello, sizeof(g_szHello) - 1) == 0);
     195
     196//        RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL,  NULL), VERR_TIMEOUT);
     197//        RTTESTI_CHECK_RC(RTPoll(hSet, 1, NULL,  NULL), VERR_TIMEOUT);
     198    }
     199
     200
     201    /*
     202     * Close the write socket, checking that we get error returns.
     203     */
     204    RTSocketShutdown(hSocketW, true, true);
     205    RTSocketClose(hSocketW);
     206
     207    uint32_t fEvents = 0;
     208    idReady = 0;
     209    RTTESTI_CHECK_RC(RTPoll(hSet, 0, &fEvents, &idReady), VINF_SUCCESS);
     210    RTTESTI_CHECK_MSG(idReady == 2 || idReady == 12, ("idReady=%u\n", idReady));
     211    RTTESTI_CHECK_MSG(fEvents & RTPOLL_EVT_ERROR, ("fEvents=%#x\n", fEvents));
     212
     213    RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 2), VINF_SUCCESS);
     214    RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 12), VINF_SUCCESS);
     215
     216    RTSocketClose(hSocketR);
     217
     218    /*
     219     * Ditto for the pipe end.
     220     */
     221    RTPipeClose(hPipeW);
     222
     223    idReady = fEvents = 0;
     224    RTTESTI_CHECK_RC(RTPoll(hSet, 0, &fEvents, &idReady), VINF_SUCCESS);
     225    RTTESTI_CHECK_MSG(idReady == 1 || idReady == 11, ("idReady=%u\n", idReady));
     226    RTTESTI_CHECK_MSG(fEvents & RTPOLL_EVT_ERROR, ("fEvents=%#x\n", fEvents));
     227
     228    RTPipeClose(hPipeR);
     229
     230    RTTESTI_CHECK_RC(RTPollSetDestroy(hSet), VINF_SUCCESS);
     231RTLogFlush(NULL);
     232}
    39233
    40234
     
    99293
    100294    RTTESTI_CHECK_RC_RETV(RTPollSetDestroy(hSet), VINF_SUCCESS);
    101 
    102 
    103 
    104295}
    105296
     
    425616        RTAssertSetQuiet(fQuiet);
    426617        RTAssertSetMayPanic(fMayPanic);
     618
     619        tstRTPoll3();
    427620    }
    428621
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette