(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.27 static void BlockingServer_Init(int type, SOCKET *sock, SOCKADDR_IN *addr);
 77 cs130_tom 1.25 static void BlockingServer_ProcessConnection(struct ServerInfo *t);
 78 cs130_tom 1.24 static void StartBlockingClients(int *serverPort);
 79                static void BlockingClient(int *serverPort);
 80                static void BlockingServer();
 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.27 // BlockingServer_Init creates socket sock of type type and returns assigned port number in addr.
128                static void 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_doug 1.8  }
162                 
163 cs130_tom  1.25 static void BlockingServer() // listens for incoming connections and accepts up to NUM_CLIENTS connections at once
164 rizwank    1.3  {
165 cs130_tom  1.25 	struct ServerInfo *threads;
166                 	int threadIndex = 0;
167 cs130_tom  1.24 	int serverPort = 0;
168 cs130_doug 1.11 
169                 	SOCKET sock;
170                 	SOCKADDR_IN server;
171 cs130_tom  1.10 
172 cs130_tom  1.27 	BlockingServer_Init(SOCK_STREAM, &sock, &server);
173 cs130_tom  1.9  
174 cs130_tom  1.19 	// allocate enough space to keep track of NUM_CLIENTS connections
175 cs130_tom  1.25 	threads = malloc(sizeof(struct ServerInfo) * NUM_CLIENTS);
176                 	memset(threads, 0, sizeof(struct ServerInfo) * NUM_CLIENTS);
177 cs130_tom  1.12 
178 cs130_tom  1.19 	// set the port parameter; clients now know we're ready to accept connections
179 cs130_tom  1.24 	serverPort = server.sin_port;
180 cs130_tom  1.17 
181 cs130_tom  1.23 	// bound to port; now we can start clients
182 cs130_tom  1.24 	CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &StartBlockingClients, &serverPort, 0, NULL);
183 cs130_tom  1.23 
184 cs130_tom  1.19 	// we require one connection from each client thread
185 cs130_tom  1.25 	for (threadIndex = 0; threadIndex < NUM_CLIENTS; threadIndex++) {
186 cs130_tom  1.19 			// accept connection
187 cs130_tom  1.25 			threads[threadIndex].connectedSocket = accept(sock, (SOCKADDR *) &threads[threadIndex].clientAddr, &sizeofSOCKADDR_IN); // this can be modified to include the address of the remote socket
188                 			ok(threads[threadIndex].connectedSocket != INVALID_SOCKET, "error accepting socket\n");
189 cs130_tom  1.19 
190                 			// spawn thread to handle sending data
191 cs130_tom  1.25 			threads[threadIndex].threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingServer_ProcessConnection, &threads[threadIndex], 0, &threads[threadIndex].threadID);
192 cs130_doug 1.8  	}
193 cs130_tom  1.5  
194 cs130_tom  1.19 	// wait for all clients to receive data before cleaning up
195 cs130_tom  1.25 	for(threadIndex = 0; threadIndex < NUM_CLIENTS; threadIndex++) {
196                 		WaitForSingleObject(threads[threadIndex].threadHandle, INFINITE);
197 cs130_tom  1.24 	}
198 cs130_tom  1.5  
199 cs130_tom  1.25 	free(threads);
200 cs130_tom  1.27 }
201                 
202                 static void BlockingServer_ProcessConnection(struct ServerInfo *t)
203                 {
204                 	// this will handle all connections to the server, it's in its own function to allow for multithreading
205                 	int bClosed;
206                 	int totCharsSent = 0;
207                 	int numCharsSent;
208                 	const int charsPerSend = 2000;
209                 
210                 	// loop and send data
211                 	while( totCharsSent < TEST_DATA_SIZE ) {
212                 		numCharsSent = send(t->connectedSocket, gTestData+totCharsSent, (totCharsSent + charsPerSend <= TEST_DATA_SIZE) ? charsPerSend : TEST_DATA_SIZE - totCharsSent, 0);
213                 		ok( numCharsSent != SOCKET_ERROR, "socket error\n" );
214                 
215                 		// pass if send buffer is full
216                 		if(numCharsSent == 0) {
217                 			Sleep(100);
218                 		}
219                 
220                 		totCharsSent += numCharsSent;
221 cs130_tom  1.27 	}
222                 
223                 	bClosed = !closesocket(t->connectedSocket);
224                 	ok(bClosed,"Error closing socket\n");
225 rizwank    1.3  }
226                 
227 cs130_tom  1.24 static void StartBlockingClients(int *serverPort)
228 rizwank    1.3  {
229 cs130_tom  1.25 	int threadIndex = 0;
230                 	struct ThreadInfo *clientThreads;
231 cs130_tom  1.9  
232 cs130_tom  1.25 	clientThreads = malloc(sizeof(struct ThreadInfo) * NUM_CLIENTS);
233                 	memset(clientThreads, 0, sizeof(struct ThreadInfo) * NUM_CLIENTS);
234 cs130_tom  1.18 
235 cs130_tom  1.25 	for(threadIndex = 0; threadIndex < NUM_CLIENTS; threadIndex++) {
236                 		clientThreads[threadIndex].Handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingClient, (void *) serverPort, 0, &clientThreads[threadIndex].ID);
237 cs130_tom  1.9  	}
238 cs130_tom  1.20 	trace("%d clients started\n", NUM_CLIENTS);
239 cs130_tom  1.9  
240 cs130_tom  1.20 	// wait for all clients to receive data before cleaning up
241 cs130_tom  1.25 	for(threadIndex = 0; threadIndex < NUM_CLIENTS; threadIndex++) {
242                 		WaitForSingleObject(clientThreads[threadIndex].Handle, INFINITE);
243 cs130_tom  1.24 	}
244 cs130_tom  1.19 
245 cs130_tom  1.25 	free(clientThreads);
246 cs130_tom  1.23 }
247                 
248                 static void test_ClientServerBlocking_1(void)
249                 {
250 cs130_tom  1.25 	struct ThreadInfo serverThread;
251 cs130_tom  1.24 	DWORD waitStatus;
252 cs130_tom  1.23 	
253                 	// start server thread
254                 	// server starts client threads after it binds to a port.
255                 	trace("starting main server thread\n");
256 cs130_tom  1.25 	serverThread.Handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingServer, NULL, 0, &serverThread.ID);
257 cs130_tom  1.23 
258 cs130_tom  1.24 	// server thread needs to end before cleaning up
259 cs130_tom  1.25 	waitStatus = WaitForSingleObject(serverThread.Handle, TEST_TIMEOUT * 1000);
260 cs130_tom  1.24 	ok( waitStatus != WAIT_TIMEOUT, "test did not complete in time\n" );
261 rizwank    1.3  }
262                 
263 cs130_tom  1.4  static void test_Startup(void)
264 rizwank    1.3  {
265 cs130_tom  1.4  	// initialize application
266                 	WSADATA wsaData;
267 cs130_tom  1.22 	int wsastartup_result;
268 cs130_tom  1.14 	int versionOK;
269                 
270 cs130_tom  1.19 	// check for compatible winsock version
271 cs130_tom  1.14 	wsastartup_result = WSAStartup(MAKEWORD(1,1), &wsaData);
272                 	versionOK = (LOBYTE(wsaData.wVersion) == 1) && (HIBYTE(wsaData.wVersion) == 1);
273                 
274 cs130_tom  1.24 	ok( versionOK , "WSAStartup returns an incompatible sockets version\n");
275 cs130_tom  1.14 	if ( !versionOK ) {
276 cs130_tom  1.4  		WSACleanup();
277                 		exit(0);
278                 	}
279                 
280 cs130_tom  1.24 	ok((wsastartup_result == NO_ERROR), "Error in WSAStartup()\n");
281 cs130_tom  1.22 	trace("startup ok\n");
282                 }
283                 
284                 static void test_Cleanup(void)
285                 {
286                 	int cleanupOK;
287                 
288                 	cleanupOK = ! WSACleanup();
289                 
290 cs130_tom  1.24 	ok( cleanupOK , "error in WSACleanup()\n");
291 cs130_tom  1.22 	trace("cleanup ok\n");
292 rizwank    1.3  }
293 cs130_tom  1.4  
294 rizwank    1.1  START_TEST(wsock32_main)
295                 {
296 cs130_tom  1.22 	const int numTests = 3;
297 cs130_tom  1.24 	gTestData = malloc(TEST_DATA_SIZE);
298 cs130_tom  1.22   
299                 	trace("test 1 of %d:\n", numTests);
300                 	test_Startup();
301                   
302                 	trace("test 2 of %d:\n", numTests);
303                 	test_ClientServerBlocking_1();
304                 	
305                 	trace("test 3 of %d:\n", numTests);
306                 	test_Cleanup();
307                 
308 cs130_tom  1.4    trace("all tests done\n");
309 cs130_tom  1.20 
310 cs130_tom  1.24 	free(gTestData);
311 rizwank    1.1  }

Rizwan Kassim
Powered by
ViewCVS 0.9.2