Back to index

lightning-sunbird  0.9+nobinonly
zerolen.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039  * Test: zerolen.c 
00040  *
00041  * Description: a test for Bugzilla bug #17699.  We perform
00042  * the same test for PR_Writev, PR_Write, and PR_Send.  In
00043  * each test the server thread first fills up the connection
00044  * to the client so that the next write operation will fail
00045  * with EAGAIN.  Then it calls PR_Writev, PR_Write, or PR_Send
00046  * with a zero-length buffer.  The client thread initially
00047  * does not read so that the connection can be filled up.
00048  * Then it empties the connection so that the server thread's
00049  * PR_Writev, PR_Write, or PR_Send call can succeed.
00050  *
00051  * Bug #17699 is specific to the pthreads version on Unix,
00052  * so on other platforms this test does nothing.
00053  */
00054 
00055 #ifndef XP_UNIX
00056 
00057 #include <stdio.h>
00058 
00059 int main()
00060 {
00061     printf("PASS\n");
00062     return 0;
00063 }
00064 
00065 #else /* XP_UNIX */
00066 
00067 #include "nspr.h"
00068 #include "private/pprio.h"
00069 
00070 #include <stdio.h>
00071 #include <stdlib.h>
00072 #include <string.h>
00073 #include <errno.h>
00074 #include <unistd.h>
00075 
00076 static void ClientThread(void *arg)
00077 {
00078     PRFileDesc *sock;
00079     PRNetAddr addr;
00080     PRUint16 port = (PRUint16) arg;
00081     char buf[1024];
00082     PRInt32 nbytes;
00083 
00084     sock = PR_NewTCPSocket();
00085     if (NULL == sock) {
00086         fprintf(stderr, "PR_NewTCPSocket failed\n");
00087         exit(1);
00088     }
00089     if (PR_InitializeNetAddr(PR_IpAddrLoopback, port, &addr) == PR_FAILURE) {
00090         fprintf(stderr, "PR_InitializeNetAddr failed\n");
00091         exit(1);
00092     }
00093     if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
00094         fprintf(stderr, "PR_Connect failed\n");
00095         exit(1);
00096     }
00097     /*
00098      * Sleep 5 seconds to force the server thread to get EAGAIN.
00099      */
00100     if (PR_Sleep(PR_SecondsToInterval(5)) == PR_FAILURE) {
00101         fprintf(stderr, "PR_Sleep failed\n");
00102         exit(1);
00103     }
00104     /*
00105      * Then start reading.
00106      */
00107     while ((nbytes = PR_Read(sock, buf, sizeof(buf))) > 0) {
00108         /* empty loop body */
00109     }
00110     if (-1 == nbytes) {
00111         fprintf(stderr, "PR_Read failed\n");
00112         exit(1);
00113     }
00114     if (PR_Close(sock) == PR_FAILURE) {
00115         fprintf(stderr, "PR_Close failed\n");
00116         exit(1);
00117     }
00118 }
00119 
00120 int main()
00121 {
00122     PRFileDesc *listenSock;
00123     PRFileDesc *acceptSock;
00124     int osfd;
00125     PRThread *clientThread;
00126     PRNetAddr addr;
00127     char buf[1024];
00128     PRInt32 nbytes;
00129     PRIOVec iov;
00130 
00131     memset(buf, 0, sizeof(buf)); /* Initialize the buffer. */
00132     listenSock = PR_NewTCPSocket();
00133     if (NULL == listenSock) {
00134         fprintf(stderr, "PR_NewTCPSocket failed\n");
00135         exit(1);
00136     }
00137     if (PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr) == PR_FAILURE) {
00138         fprintf(stderr, "PR_InitializeNetAddr failed\n");
00139         exit(1);
00140     }
00141     if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
00142         fprintf(stderr, "PR_Bind failed\n");
00143         exit(1);
00144     }
00145     /* Find out what port number we are bound to. */
00146     if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
00147         fprintf(stderr, "PR_GetSockName failed\n");
00148         exit(1);
00149     }
00150     if (PR_Listen(listenSock, 5) == PR_FAILURE) {
00151         fprintf(stderr, "PR_Listen failed\n");
00152         exit(1);
00153     }
00154 
00155     /*
00156      * First test PR_Writev.
00157      */
00158     clientThread = PR_CreateThread(PR_USER_THREAD,
00159             ClientThread, (void *) PR_ntohs(PR_NetAddrInetPort(&addr)),
00160             PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
00161     if (NULL == clientThread) {
00162         fprintf(stderr, "PR_CreateThread failed\n");
00163         exit(1);
00164     }
00165     acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
00166     if (NULL == acceptSock) {
00167         fprintf(stderr, "PR_Accept failed\n");
00168         exit(1);
00169     }
00170     osfd = PR_FileDesc2NativeHandle(acceptSock);
00171     while ((nbytes = write(osfd, buf, sizeof(buf))) != -1) {
00172         /* empty loop body */
00173     }
00174     if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) {
00175         fprintf(stderr, "write failed\n");
00176         exit(1);
00177     }
00178     iov.iov_base = buf;
00179     iov.iov_len = 0;
00180     printf("calling PR_Writev with a zero-length buffer\n");
00181     fflush(stdout);
00182     nbytes = PR_Writev(acceptSock, &iov, 1, PR_INTERVAL_NO_TIMEOUT);
00183     if (nbytes != 0) {
00184         fprintf(stderr, "PR_Writev should return 0 but returns %d\n", nbytes);
00185         exit(1);
00186     }
00187     if (PR_Close(acceptSock) == PR_FAILURE) {
00188         fprintf(stderr, "PR_Close failed\n");
00189         exit(1);
00190     }
00191     if (PR_JoinThread(clientThread) == PR_FAILURE) {
00192         fprintf(stderr, "PR_JoinThread failed\n");
00193         exit(1);
00194     }
00195 
00196     /*
00197      * Then test PR_Write.
00198      */
00199     clientThread = PR_CreateThread(PR_USER_THREAD,
00200             ClientThread, (void *) PR_ntohs(PR_NetAddrInetPort(&addr)),
00201             PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
00202     if (NULL == clientThread) {
00203         fprintf(stderr, "PR_CreateThread failed\n");
00204         exit(1);
00205     }
00206     acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
00207     if (NULL == acceptSock) {
00208         fprintf(stderr, "PR_Accept failed\n");
00209         exit(1);
00210     }
00211     osfd = PR_FileDesc2NativeHandle(acceptSock);
00212     while ((nbytes = write(osfd, buf, sizeof(buf))) != -1) {
00213         /* empty loop body */
00214     }
00215     if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) {
00216         fprintf(stderr, "write failed\n");
00217         exit(1);
00218     }
00219     printf("calling PR_Write with a zero-length buffer\n");
00220     fflush(stdout);
00221     nbytes = PR_Write(acceptSock, buf, 0);
00222     if (nbytes != 0) {
00223         fprintf(stderr, "PR_Write should return 0 but returns %d\n", nbytes);
00224         exit(1);
00225     }
00226     if (PR_Close(acceptSock) == PR_FAILURE) {
00227         fprintf(stderr, "PR_Close failed\n");
00228         exit(1);
00229     }
00230     if (PR_JoinThread(clientThread) == PR_FAILURE) {
00231         fprintf(stderr, "PR_JoinThread failed\n");
00232         exit(1);
00233     }
00234 
00235     /*
00236      * Finally test PR_Send.
00237      */
00238     clientThread = PR_CreateThread(PR_USER_THREAD,
00239             ClientThread, (void *) PR_ntohs(PR_NetAddrInetPort(&addr)),
00240             PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
00241     if (NULL == clientThread) {
00242         fprintf(stderr, "PR_CreateThread failed\n");
00243         exit(1);
00244     }
00245     acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
00246     if (NULL == acceptSock) {
00247         fprintf(stderr, "PR_Accept failed\n");
00248         exit(1);
00249     }
00250     osfd = PR_FileDesc2NativeHandle(acceptSock);
00251     while ((nbytes = write(osfd, buf, sizeof(buf))) != -1) {
00252         /* empty loop body */
00253     }
00254     if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) {
00255         fprintf(stderr, "write failed\n");
00256         exit(1);
00257     }
00258     printf("calling PR_Send with a zero-length buffer\n");
00259     fflush(stdout);
00260     nbytes = PR_Send(acceptSock, buf, 0, 0, PR_INTERVAL_NO_TIMEOUT);
00261     if (nbytes != 0) {
00262         fprintf(stderr, "PR_Send should return 0 but returns %d\n", nbytes);
00263         exit(1);
00264     }
00265     if (PR_Close(acceptSock) == PR_FAILURE) {
00266         fprintf(stderr, "PR_Close failed\n");
00267         exit(1);
00268     }
00269     if (PR_JoinThread(clientThread) == PR_FAILURE) {
00270         fprintf(stderr, "PR_JoinThread failed\n");
00271         exit(1);
00272     }
00273 
00274     if (PR_Close(listenSock) == PR_FAILURE) {
00275         fprintf(stderr, "PR_Close failed\n");
00276         exit(1);
00277     }
00278     printf("PASS\n");
00279     return 0;
00280 }
00281 
00282 #endif /* XP_UNIX */