(file) Return to wsock32_main.c CVS log (file) (dir) Up to [RizwankCVS] / wine4 / wine / dlls / wsock32 / tests

  1 rizwank 1.1 /*
  2 cs130_tom 1.26  * Unit tests for 32-bit WinSock 1.1 functions in Wine
  3 rizwank   1.1   *
  4 rizwank   1.3   * Copyright (c) 2005 Thomas Kho, Fredy Garcia, Douglas Rosenberg
  5 rizwank   1.1   *
  6                 * This library is free software; you can redistribute it and/or
  7                 * modify it under the terms of the GNU Lesser General Public
  8                 * License as published by the Free Software Foundation; either
  9                 * version 2.1 of the License, or (at your option) any later version.
 10                 *
 11                 * This library is distributed in the hope that it will be useful,
 12                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14                 * Lesser General Public License for more details.
 15                 *
 16                 * You should have received a copy of the GNU Lesser General Public
 17                 * License along with this library; if not, write to the Free Software
 18                 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 19                 */
 20                
 21                #include <stdio.h>
 22                
 23 rizwank   1.3  #include <windows.h>
 24 cs130_tom 1.4  #include <winsock.h>
 25                #include <wtypes.h>
 26                #include <winerror.h>
 27 rizwank   1.1  
 28                #ifndef STANDALONE
 29                #include "wine/test.h"
 30                #else
 31                #include <assert.h>
 32                #define START_TEST(name) main(int argc, char **argv)
 33                #define ok(condition, msg) \
 34                	do { \
 35                		if(!(condition)) \
 36                		{ \
 37                			fprintf(stderr,"failed at %d\n",__LINE__); \
 38                			exit(0); \
 39                		} \
 40                	} while(0)
 41                
 42                #define todo_wine
 43                #endif
 44                
 45 cs130_tom 1.19 // clients threads to create
 46 cs130_tom 1.22 #define NUM_CLIENTS 64
 47 cs130_tom 1.19 
 48 cs130_tom 1.6  // amount of data to transfer from each client to server
 49 cs130_tom 1.19 #define TEST_DATA_SIZE 145243
 50 cs130_tom 1.4  
 51 cs130_tom 1.24 // max time (seconds) to run test
 52                #define TEST_TIMEOUT 10
 53 cs130_tom 1.19 
 54                // we often pass this size by reference
 55 cs130_tom 1.12 int sizeofSOCKADDR_IN = sizeof(SOCKADDR_IN);
 56 cs130_tom 1.19 
 57                // global test data; server sends it to client, then client verifies it
 58 cs130_tom 1.24 char *gTestData;
 59 cs130_tom 1.4  
 60 cs130_tom 1.25 struct ThreadInfo {
 61 cs130_tom 1.16 	HANDLE Handle;
 62                	DWORD ID;
 63                };
 64                
 65 cs130_tom 1.29 struct BlockingServerConnection {
 66                	struct ThreadInfo serverThread;
 67 cs130_tom 1.25 	SOCKET connectedSocket; // socket to communicate with client
 68                	SOCKADDR_IN clientAddr; // client info
 69 cs130_tom 1.12 };
 70                
 71 cs130_tom 1.4  static void test_Startup(void);
 72 cs130_tom 1.23 static void test_ClientServerBlocking_1(void);
 73 cs130_tom 1.22 static void test_Cleanup(void);
 74 cs130_tom 1.23 
 75 cs130_tom 1.28 static void BlockingClient(int *serverPort);
 76                static int BlockingServer_Init(int type, SOCKET *sock, SOCKADDR_IN *addr);
 77                static void BlockingServer(SOCKET *sock);
 78 cs130_tom 1.29 static struct BlockingServerConnection * BlockingServerConnection_New(SOCKET sock, SOCKADDR_IN clientAddr);
 79                static void BlockingServerConnection_Run(struct BlockingServerConnection *t);
 80                static void BlockingServerConnection_Delete(struct BlockingServerConnection *c);
 81 cs130_tom 1.23 
 82 cs130_tom 1.25 static void BlockingClient(int *serverPort)
 83 cs130_tom 1.5  {
 84                	SOCKET sock;
 85 cs130_tom 1.26 	SOCKADDR_IN server;
 86 cs130_tom 1.6  	HOSTENT *hp;
 87 cs130_tom 1.16 	int connectError;
 88                	int totCharsReceived = 0;
 89                	int numCharsReceived;
 90                	int memSame;
 91                	char buf[1001];
 92 cs130_tom 1.12 
 93 cs130_tom 1.26 	// create socket
 94                	sock = socket(AF_INET, SOCK_STREAM, 0);
 95                	ok( sock != INVALID_SOCKET , "Error in socket()\n");
 96                	if (sock == INVALID_SOCKET) {
 97                		WSACleanup();
 98                		exit(0);
 99                	}
100 cs130_tom 1.5  
101 cs130_tom 1.6  	hp = gethostbyname("localhost");
102                
103                	server.sin_family = AF_INET;
104                	server.sin_addr = *(struct in_addr *) hp->h_addr;
105                	server.sin_port = *serverPort;
106 cs130_tom 1.4  
107 cs130_tom 1.19 	// connect to server
108 cs130_tom 1.16 	connectError = connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr));
109                	ok( !connectError , "client cannot connect to host\n");
110                	if(connectError) {
111 cs130_tom 1.12 		WSACleanup();
112                		exit(0);
113                	}
114 cs130_tom 1.19 
115                	// start receiving data from server
116 cs130_tom 1.16 	while( totCharsReceived < TEST_DATA_SIZE ) {
117                		numCharsReceived = recv(sock, buf, 1000, 0);
118 cs130_tom 1.24 		ok( numCharsReceived > 0, "socket was closed unexpectedly\n" );
119 cs130_tom 1.19 		
120                		// check received data againt global test data
121 cs130_tom 1.24 		memSame = ! memcmp(buf,gTestData+totCharsReceived,numCharsReceived);
122                		ok( memSame, "data integrity lost during transfer\n" );
123 cs130_tom 1.19 		totCharsReceived += numCharsReceived;
124 cs130_tom 1.12 	}
125 rizwank   1.1  }
126                
127 cs130_tom 1.28 static int BlockingServer_Init(int type, SOCKET *sock, SOCKADDR_IN *addr)
128 cs130_doug 1.8  {
129 cs130_tom  1.29 	// BlockingServer_Init creates socket sock of type type and returns assigned port number in addr.
130                 	// returns server port number
131                 
132 cs130_tom  1.27 	SOCKADDR_IN tmpAddr;
133                 	int bindOK;
134                 	int listenReturn;
135 cs130_tom  1.17 
136 cs130_tom  1.27 	// create socket
137                 	*sock = socket(AF_INET, type, 0);
138                 	ok( *sock != INVALID_SOCKET , "Error in socket()\n");
139                 	if (*sock == INVALID_SOCKET) {
140                 		WSACleanup();
141                 		exit(0);
142                 	}
143 cs130_tom  1.25 
144 cs130_tom  1.27 	addr->sin_family = AF_INET;
145                 	addr->sin_addr.s_addr = INADDR_ANY;
146                 	addr->sin_port = htons(0);
147 cs130_tom  1.25 
148 cs130_tom  1.27 	// bind socket to port
149                 	bindOK = !bind(*sock, (const SOCKADDR *) addr, sizeofSOCKADDR_IN);
150                 	ok( bindOK , "Error binding client to socket\n");
151                 	if( !bindOK ) {
152                 		WSACleanup();
153                 		exit(0);
154 cs130_tom  1.17 	}
155                 
156 cs130_tom  1.27 	// get port number
157                 	getsockname(*sock, (SOCKADDR *) &tmpAddr, &sizeofSOCKADDR_IN);
158                 	addr->sin_port = tmpAddr.sin_port;
159                 
160                 	// listen on port
161                 	listenReturn = listen(*sock, NUM_CLIENTS);
162                 	ok(listenReturn != SOCKET_ERROR, "error listening on socket\n");
163 cs130_tom  1.28 
164                 	return addr->sin_port;
165 cs130_doug 1.8  }
166                 
167 cs130_tom  1.28 static void BlockingServer(SOCKET *sock) // listens for incoming connections and accepts up to NUM_CLIENTS connections at once
168 rizwank    1.3  {
169 cs130_tom  1.29 	struct BlockingServerConnection *connections[NUM_CLIENTS];
170                 	int connIndex = 0;
171                 	SOCKET tmpSock;
172                 	SOCKADDR_IN tmpSockAddr;
173 cs130_tom  1.12 
174 cs130_tom  1.19 	// we require one connection from each client thread
175 cs130_tom  1.29 	for (connIndex = 0; connIndex < NUM_CLIENTS; connIndex++) {
176 cs130_tom  1.19 			// accept connection
177 cs130_tom  1.29 			tmpSock = accept(*sock, (SOCKADDR *) &tmpSockAddr, &sizeofSOCKADDR_IN);
178                 			ok(tmpSock != INVALID_SOCKET, "error accepting socket\n");
179 cs130_tom  1.19 
180 cs130_tom  1.29 			// handle new connection
181                 			connections[connIndex] = BlockingServerConnection_New(tmpSock, tmpSockAddr);
182 cs130_doug 1.8  	}
183 cs130_tom  1.5  
184 cs130_tom  1.29 	// clean up connections
185                 	for(connIndex = 0; connIndex < NUM_CLIENTS; connIndex++) {
186                 		BlockingServerConnection_Delete(connections[connIndex]);
187 cs130_tom  1.24 	}
188 cs130_tom  1.29 }
189                 
190                 static struct BlockingServerConnection * BlockingServerConnection_New(SOCKET sock, SOCKADDR_IN clientAddr)
191                 {
192                 	struct BlockingServerConnection *connection;
193                 	connection = malloc(sizeof(struct BlockingServerConnection));
194                 	memset(connection, 0, sizeof(struct BlockingServerConnection));
195 cs130_tom  1.5  
196 cs130_tom  1.29 	connection->connectedSocket = sock;
197                 	connection->clientAddr = clientAddr;
198                 
199                 	// spawn thread to handle sending data
200                 	connection->serverThread.Handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingServerConnection_Run, connection, 0, &connection->serverThread.ID);
201                 
202                 	return connection;
203 cs130_tom  1.27 }
204                 
205 cs130_tom  1.29 static void BlockingServerConnection_Run(struct BlockingServerConnection *connection)
206 cs130_tom  1.27 {
207                 	// this will handle all connections to the server, it's in its own function to allow for multithreading
208                 	int bClosed;
209                 	int totCharsSent = 0;
210                 	int numCharsSent;
211                 	const int charsPerSend = 2000;
212                 
213                 	// loop and send data
214                 	while( totCharsSent < TEST_DATA_SIZE ) {
215 cs130_tom  1.29 		numCharsSent = send(connection->connectedSocket, gTestData+totCharsSent, (totCharsSent + charsPerSend <= TEST_DATA_SIZE) ? charsPerSend : TEST_DATA_SIZE - totCharsSent, 0);
216 cs130_tom  1.27 		ok( numCharsSent != SOCKET_ERROR, "socket error\n" );
217                 
218                 		// pass if send buffer is full
219                 		if(numCharsSent == 0) {
220                 			Sleep(100);
221                 		}
222                 
223                 		totCharsSent += numCharsSent;
224                 	}
225                 
226 cs130_tom  1.29 	bClosed = !closesocket(connection->connectedSocket);
227 cs130_tom  1.27 	ok(bClosed,"Error closing socket\n");
228 rizwank    1.3  }
229                 
230 cs130_tom  1.29 static void BlockingServerConnection_Delete(struct BlockingServerConnection *c)
231                 {
232                 	// wait for client to receive data before cleaning up
233                 	WaitForSingleObject(c->serverThread.Handle, INFINITE);
234                 
235                 	free(c);
236                 }
237                 
238 cs130_tom  1.28 static void test_ClientServerBlocking_1(void)
239 rizwank    1.3  {
240 cs130_tom  1.28 	struct ThreadInfo serverThread;
241 cs130_tom  1.29 	struct ThreadInfo *clientThreads;
242 cs130_tom  1.28 	DWORD waitStatus;
243                 	SOCKET sock;
244                 	SOCKADDR_IN server;
245                 	int serverPort;
246 cs130_tom  1.25 	int threadIndex = 0;
247 cs130_tom  1.9  
248 cs130_tom  1.28 	// create socket, bind server and start listening
249                 	serverPort = BlockingServer_Init(SOCK_STREAM, &sock, &server);
250                 
251                 	// start server thread
252                 	trace("starting server thread\n");
253                 	serverThread.Handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingServer, &sock, 0, &serverThread.ID);
254                 
255                 	// start client threads
256 cs130_tom  1.25 	clientThreads = malloc(sizeof(struct ThreadInfo) * NUM_CLIENTS);
257                 	memset(clientThreads, 0, sizeof(struct ThreadInfo) * NUM_CLIENTS);
258 cs130_tom  1.18 
259 cs130_tom  1.25 	for(threadIndex = 0; threadIndex < NUM_CLIENTS; threadIndex++) {
260 cs130_tom  1.28 		clientThreads[threadIndex].Handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingClient, (void *) &serverPort, 0, &clientThreads[threadIndex].ID);
261 cs130_tom  1.9  	}
262 cs130_tom  1.20 	trace("%d clients started\n", NUM_CLIENTS);
263 cs130_tom  1.9  
264 cs130_tom  1.28 	// server thread needs to end before cleaning up
265                 	waitStatus = WaitForSingleObject(serverThread.Handle, TEST_TIMEOUT * 1000);
266                 	ok( waitStatus != WAIT_TIMEOUT, "test did not complete in time\n" );
267                 
268 cs130_tom  1.20 	// wait for all clients to receive data before cleaning up
269 cs130_tom  1.25 	for(threadIndex = 0; threadIndex < NUM_CLIENTS; threadIndex++) {
270                 		WaitForSingleObject(clientThreads[threadIndex].Handle, INFINITE);
271 cs130_tom  1.24 	}
272 cs130_tom  1.19 
273 cs130_tom  1.25 	free(clientThreads);
274 rizwank    1.3  }
275                 
276 cs130_tom  1.4  static void test_Startup(void)
277 rizwank    1.3  {
278 cs130_tom  1.4  	// initialize application
279                 	WSADATA wsaData;
280 cs130_tom  1.22 	int wsastartup_result;
281 cs130_tom  1.14 	int versionOK;
282                 
283 cs130_tom  1.19 	// check for compatible winsock version
284 cs130_tom  1.14 	wsastartup_result = WSAStartup(MAKEWORD(1,1), &wsaData);
285                 	versionOK = (LOBYTE(wsaData.wVersion) == 1) && (HIBYTE(wsaData.wVersion) == 1);
286                 
287 cs130_tom  1.24 	ok( versionOK , "WSAStartup returns an incompatible sockets version\n");
288 cs130_tom  1.14 	if ( !versionOK ) {
289 cs130_tom  1.4  		WSACleanup();
290                 		exit(0);
291                 	}
292                 
293 cs130_tom  1.24 	ok((wsastartup_result == NO_ERROR), "Error in WSAStartup()\n");
294 cs130_tom  1.22 	trace("startup ok\n");
295                 }
296                 
297                 static void test_Cleanup(void)
298                 {
299                 	int cleanupOK;
300                 
301                 	cleanupOK = ! WSACleanup();
302                 
303 cs130_tom  1.24 	ok( cleanupOK , "error in WSACleanup()\n");
304 cs130_tom  1.22 	trace("cleanup ok\n");
305 rizwank    1.3  }
306 cs130_tom  1.4  
307 rizwank    1.1  START_TEST(wsock32_main)
308                 {
309 cs130_tom  1.22 	const int numTests = 3;
310 cs130_tom  1.24 	gTestData = malloc(TEST_DATA_SIZE);
311 cs130_tom  1.22   
312                 	trace("test 1 of %d:\n", numTests);
313                 	test_Startup();
314                   
315                 	trace("test 2 of %d:\n", numTests);
316                 	test_ClientServerBlocking_1();
317                 	
318                 	trace("test 3 of %d:\n", numTests);
319                 	test_Cleanup();
320                 
321 cs130_tom  1.29 	trace("all tests done\n");
322 cs130_tom  1.20 
323 cs130_tom  1.24 	free(gTestData);
324 rizwank    1.1  }

Rizwan Kassim
Powered by
ViewCVS 0.9.2