(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.25 struct ServerInfo {
 66                	HANDLE threadHandle;
 67                	DWORD threadID;
 68                	SOCKET connectedSocket; // socket to communicate with client
 69                	SOCKADDR_IN clientAddr; // client info
 70 cs130_tom 1.12 };
 71                
 72 cs130_tom 1.4  static void test_Startup(void);
 73 cs130_tom 1.23 static void test_ClientServerBlocking_1(void);
 74 cs130_tom 1.22 static void test_Cleanup(void);
 75 cs130_tom 1.23 
 76 cs130_tom 1.28 static void BlockingClient(int *serverPort);
 77                static int BlockingServer_Init(int type, SOCKET *sock, SOCKADDR_IN *addr);
 78                static void BlockingServer(SOCKET *sock);
 79 cs130_tom 1.25 static void BlockingServer_ProcessConnection(struct ServerInfo *t);
 80 cs130_tom 1.23 
 81 cs130_tom 1.25 static void BlockingClient(int *serverPort)
 82 cs130_tom 1.5  {
 83                	SOCKET sock;
 84 cs130_tom 1.26 	SOCKADDR_IN server;
 85 cs130_tom 1.6  	HOSTENT *hp;
 86 cs130_tom 1.16 	int connectError;
 87                	int totCharsReceived = 0;
 88                	int numCharsReceived;
 89                	int memSame;
 90                	char buf[1001];
 91 cs130_tom 1.12 
 92 cs130_tom 1.26 	// create socket
 93                	sock = socket(AF_INET, SOCK_STREAM, 0);
 94                	ok( sock != INVALID_SOCKET , "Error in socket()\n");
 95                	if (sock == INVALID_SOCKET) {
 96                		WSACleanup();
 97                		exit(0);
 98                	}
 99 cs130_tom 1.5  
100 cs130_tom 1.6  	hp = gethostbyname("localhost");
101                
102                	server.sin_family = AF_INET;
103                	server.sin_addr = *(struct in_addr *) hp->h_addr;
104                	server.sin_port = *serverPort;
105 cs130_tom 1.4  
106 cs130_tom 1.19 	// connect to server
107 cs130_tom 1.16 	connectError = connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr));
108                	ok( !connectError , "client cannot connect to host\n");
109                	if(connectError) {
110 cs130_tom 1.12 		WSACleanup();
111                		exit(0);
112                	}
113 cs130_tom 1.19 
114                	// start receiving data from server
115 cs130_tom 1.16 	while( totCharsReceived < TEST_DATA_SIZE ) {
116                		numCharsReceived = recv(sock, buf, 1000, 0);
117 cs130_tom 1.24 		ok( numCharsReceived > 0, "socket was closed unexpectedly\n" );
118 cs130_tom 1.19 		
119                		// check received data againt global test data
120 cs130_tom 1.24 		memSame = ! memcmp(buf,gTestData+totCharsReceived,numCharsReceived);
121                		ok( memSame, "data integrity lost during transfer\n" );
122 cs130_tom 1.19 		totCharsReceived += numCharsReceived;
123 cs130_tom 1.12 	}
124 rizwank   1.1  }
125                
126 cs130_tom 1.27 // BlockingServer_Init creates socket sock of type type and returns assigned port number in addr.
127 cs130_tom 1.28 // returns server port number
128                static int BlockingServer_Init(int type, SOCKET *sock, SOCKADDR_IN *addr)
129 cs130_doug 1.8  {
130 cs130_tom  1.27 	SOCKADDR_IN tmpAddr;
131                 	int bindOK;
132                 	int listenReturn;
133 cs130_tom  1.17 
134 cs130_tom  1.27 	// create socket
135                 	*sock = socket(AF_INET, type, 0);
136                 	ok( *sock != INVALID_SOCKET , "Error in socket()\n");
137                 	if (*sock == INVALID_SOCKET) {
138                 		WSACleanup();
139                 		exit(0);
140                 	}
141 cs130_tom  1.25 
142 cs130_tom  1.27 	addr->sin_family = AF_INET;
143                 	addr->sin_addr.s_addr = INADDR_ANY;
144                 	addr->sin_port = htons(0);
145 cs130_tom  1.25 
146 cs130_tom  1.27 	// bind socket to port
147                 	bindOK = !bind(*sock, (const SOCKADDR *) addr, sizeofSOCKADDR_IN);
148                 	ok( bindOK , "Error binding client to socket\n");
149                 	if( !bindOK ) {
150                 		WSACleanup();
151                 		exit(0);
152 cs130_tom  1.17 	}
153                 
154 cs130_tom  1.27 	// get port number
155                 	getsockname(*sock, (SOCKADDR *) &tmpAddr, &sizeofSOCKADDR_IN);
156                 	addr->sin_port = tmpAddr.sin_port;
157                 
158                 	// listen on port
159                 	listenReturn = listen(*sock, NUM_CLIENTS);
160                 	ok(listenReturn != SOCKET_ERROR, "error listening on socket\n");
161 cs130_tom  1.28 
162                 	return addr->sin_port;
163 cs130_doug 1.8  }
164                 
165 cs130_tom  1.28 static void BlockingServer(SOCKET *sock) // listens for incoming connections and accepts up to NUM_CLIENTS connections at once
166 rizwank    1.3  {
167 cs130_tom  1.25 	struct ServerInfo *threads;
168                 	int threadIndex = 0;
169 cs130_tom  1.9  
170 cs130_tom  1.19 	// allocate enough space to keep track of NUM_CLIENTS connections
171 cs130_tom  1.25 	threads = malloc(sizeof(struct ServerInfo) * NUM_CLIENTS);
172                 	memset(threads, 0, sizeof(struct ServerInfo) * NUM_CLIENTS);
173 cs130_tom  1.12 
174 cs130_tom  1.19 	// we require one connection from each client thread
175 cs130_tom  1.25 	for (threadIndex = 0; threadIndex < NUM_CLIENTS; threadIndex++) {
176 cs130_tom  1.19 			// accept connection
177 cs130_tom  1.28 			threads[threadIndex].connectedSocket = accept(*sock, (SOCKADDR *) &threads[threadIndex].clientAddr, &sizeofSOCKADDR_IN); // this can be modified to include the address of the remote socket
178 cs130_tom  1.25 			ok(threads[threadIndex].connectedSocket != INVALID_SOCKET, "error accepting socket\n");
179 cs130_tom  1.19 
180                 			// spawn thread to handle sending data
181 cs130_tom  1.25 			threads[threadIndex].threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingServer_ProcessConnection, &threads[threadIndex], 0, &threads[threadIndex].threadID);
182 cs130_doug 1.8  	}
183 cs130_tom  1.5  
184 cs130_tom  1.19 	// wait for all clients to receive data before cleaning up
185 cs130_tom  1.25 	for(threadIndex = 0; threadIndex < NUM_CLIENTS; threadIndex++) {
186                 		WaitForSingleObject(threads[threadIndex].threadHandle, INFINITE);
187 cs130_tom  1.24 	}
188 cs130_tom  1.5  
189 cs130_tom  1.25 	free(threads);
190 cs130_tom  1.27 }
191                 
192                 static void BlockingServer_ProcessConnection(struct ServerInfo *t)
193                 {
194                 	// this will handle all connections to the server, it's in its own function to allow for multithreading
195                 	int bClosed;
196                 	int totCharsSent = 0;
197                 	int numCharsSent;
198                 	const int charsPerSend = 2000;
199                 
200                 	// loop and send data
201                 	while( totCharsSent < TEST_DATA_SIZE ) {
202                 		numCharsSent = send(t->connectedSocket, gTestData+totCharsSent, (totCharsSent + charsPerSend <= TEST_DATA_SIZE) ? charsPerSend : TEST_DATA_SIZE - totCharsSent, 0);
203                 		ok( numCharsSent != SOCKET_ERROR, "socket error\n" );
204                 
205                 		// pass if send buffer is full
206                 		if(numCharsSent == 0) {
207                 			Sleep(100);
208                 		}
209                 
210                 		totCharsSent += numCharsSent;
211 cs130_tom  1.27 	}
212                 
213                 	bClosed = !closesocket(t->connectedSocket);
214                 	ok(bClosed,"Error closing socket\n");
215 rizwank    1.3  }
216                 
217 cs130_tom  1.28 static void test_ClientServerBlocking_1(void)
218 rizwank    1.3  {
219 cs130_tom  1.28 	struct ThreadInfo serverThread;
220                 	DWORD waitStatus;
221                 	SOCKET sock;
222                 	SOCKADDR_IN server;
223                 	int serverPort;
224 cs130_tom  1.25 	int threadIndex = 0;
225                 	struct ThreadInfo *clientThreads;
226 cs130_tom  1.9  
227 cs130_tom  1.28 	// create socket, bind server and start listening
228                 	serverPort = BlockingServer_Init(SOCK_STREAM, &sock, &server);
229                 
230                 	// start server thread
231                 	trace("starting server thread\n");
232                 	serverThread.Handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingServer, &sock, 0, &serverThread.ID);
233                 
234                 	// start client threads
235 cs130_tom  1.25 	clientThreads = malloc(sizeof(struct ThreadInfo) * NUM_CLIENTS);
236                 	memset(clientThreads, 0, sizeof(struct ThreadInfo) * NUM_CLIENTS);
237 cs130_tom  1.18 
238 cs130_tom  1.25 	for(threadIndex = 0; threadIndex < NUM_CLIENTS; threadIndex++) {
239 cs130_tom  1.28 		clientThreads[threadIndex].Handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingClient, (void *) &serverPort, 0, &clientThreads[threadIndex].ID);
240 cs130_tom  1.9  	}
241 cs130_tom  1.20 	trace("%d clients started\n", NUM_CLIENTS);
242 cs130_tom  1.9  
243 cs130_tom  1.28 	// server thread needs to end before cleaning up
244                 	waitStatus = WaitForSingleObject(serverThread.Handle, TEST_TIMEOUT * 1000);
245                 	ok( waitStatus != WAIT_TIMEOUT, "test did not complete in time\n" );
246                 
247 cs130_tom  1.20 	// wait for all clients to receive data before cleaning up
248 cs130_tom  1.25 	for(threadIndex = 0; threadIndex < NUM_CLIENTS; threadIndex++) {
249                 		WaitForSingleObject(clientThreads[threadIndex].Handle, INFINITE);
250 cs130_tom  1.24 	}
251 cs130_tom  1.19 
252 cs130_tom  1.25 	free(clientThreads);
253 rizwank    1.3  }
254                 
255 cs130_tom  1.4  static void test_Startup(void)
256 rizwank    1.3  {
257 cs130_tom  1.4  	// initialize application
258                 	WSADATA wsaData;
259 cs130_tom  1.22 	int wsastartup_result;
260 cs130_tom  1.14 	int versionOK;
261                 
262 cs130_tom  1.19 	// check for compatible winsock version
263 cs130_tom  1.14 	wsastartup_result = WSAStartup(MAKEWORD(1,1), &wsaData);
264                 	versionOK = (LOBYTE(wsaData.wVersion) == 1) && (HIBYTE(wsaData.wVersion) == 1);
265                 
266 cs130_tom  1.24 	ok( versionOK , "WSAStartup returns an incompatible sockets version\n");
267 cs130_tom  1.14 	if ( !versionOK ) {
268 cs130_tom  1.4  		WSACleanup();
269                 		exit(0);
270                 	}
271                 
272 cs130_tom  1.24 	ok((wsastartup_result == NO_ERROR), "Error in WSAStartup()\n");
273 cs130_tom  1.22 	trace("startup ok\n");
274                 }
275                 
276                 static void test_Cleanup(void)
277                 {
278                 	int cleanupOK;
279                 
280                 	cleanupOK = ! WSACleanup();
281                 
282 cs130_tom  1.24 	ok( cleanupOK , "error in WSACleanup()\n");
283 cs130_tom  1.22 	trace("cleanup ok\n");
284 rizwank    1.3  }
285 cs130_tom  1.4  
286 rizwank    1.1  START_TEST(wsock32_main)
287                 {
288 cs130_tom  1.22 	const int numTests = 3;
289 cs130_tom  1.24 	gTestData = malloc(TEST_DATA_SIZE);
290 cs130_tom  1.22   
291                 	trace("test 1 of %d:\n", numTests);
292                 	test_Startup();
293                   
294                 	trace("test 2 of %d:\n", numTests);
295                 	test_ClientServerBlocking_1();
296                 	
297                 	trace("test 3 of %d:\n", numTests);
298                 	test_Cleanup();
299                 
300 cs130_tom  1.4    trace("all tests done\n");
301 cs130_tom  1.20 
302 cs130_tom  1.24 	free(gTestData);
303 rizwank    1.1  }

Rizwan Kassim
Powered by
ViewCVS 0.9.2