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

  1 rizwank 1.1 /*
  2 rizwank 1.3  * Unit tests for 32-bit socket 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 cs130_doug 1.8 #include <string.h>
 28 rizwank    1.1 
 29                #ifndef STANDALONE
 30                #include "wine/test.h"
 31                #else
 32                #include <assert.h>
 33                #define START_TEST(name) main(int argc, char **argv)
 34                #define ok(condition, msg) \
 35                	do { \
 36                		if(!(condition)) \
 37                		{ \
 38                			fprintf(stderr,"failed at %d\n",__LINE__); \
 39                			exit(0); \
 40                		} \
 41                	} while(0)
 42                
 43                #define todo_wine
 44                #endif
 45                
 46 cs130_tom  1.19 // clients threads to create
 47 cs130_tom  1.22 #define NUM_CLIENTS 64
 48 cs130_tom  1.19 
 49 cs130_tom  1.6  // amount of data to transfer from each client to server
 50 cs130_tom  1.19 #define TEST_DATA_SIZE 145243
 51 cs130_tom  1.4  
 52 cs130_tom  1.19 // tracks number of clients that have successfull transferred data
 53 cs130_tom  1.21 volatile int clientsDone = 0;
 54 cs130_tom  1.19 
 55                 // we often pass this size by reference
 56 cs130_tom  1.12 int sizeofSOCKADDR_IN = sizeof(SOCKADDR_IN);
 57 cs130_tom  1.19 
 58                 // global test data; server sends it to client, then client verifies it
 59 cs130_tom  1.15 char *testData;
 60 cs130_tom  1.7  
 61 cs130_tom  1.4  struct TestParams {
 62 cs130_tom  1.5  	int serverSock;
 63                 	int serverType;
 64 cs130_tom  1.4  	int serverPort;
 65                 	int clientPort[NUM_CLIENTS];
 66                 };
 67                 
 68                 struct ClientParams {
 69                 	struct TestParams *test;
 70                 	int clientNum; // 1...NUM_CLIENTS
 71                 };
 72                 
 73 cs130_tom  1.20 struct MyThread {
 74 cs130_tom  1.16 	HANDLE Handle;
 75                 	DWORD ID;
 76                 };
 77                 
 78 cs130_tom  1.12 struct ServerThread {
 79 cs130_doug 1.13 	HANDLE ServerThread;
 80                 	DWORD ServerThreadID;
 81                 	SOCKET ConnectedSocket; // socket to communicate with client
 82 cs130_tom  1.12 	SOCKADDR_IN Client; // client info
 83                 };
 84                 
 85 cs130_tom  1.4  static void test_Startup(void);
 86 cs130_tom  1.23 static void test_ClientServerBlocking_1(void);
 87 cs130_tom  1.22 static void test_Cleanup(void);
 88 cs130_tom  1.23 
 89                 static void StartBlockingClients(volatile int *serverPort);
 90                 static void BlockingClient(volatile int *serverPort);
 91                 static void BlockingServer(volatile int *port);
 92                 
 93 rizwank    1.1  
 94 cs130_tom  1.5  // StartNetworkApp creates socket sock of type type and returns assigned port number in addr.
 95                 void StartNetworkApp(int type, SOCKET *sock, SOCKADDR_IN *addr)
 96 rizwank    1.1  {
 97 cs130_tom  1.5  	SOCKADDR_IN tmpAddr;
 98                 	int tmpAddrSize;
 99 cs130_tom  1.19 	int bindOK;
100 cs130_tom  1.4  
101 cs130_tom  1.19 	// create socket
102 cs130_tom  1.5  	*sock = socket(AF_INET, type, 0);
103 cs130_tom  1.19 	ok( *sock != INVALID_SOCKET , "Error in socket()");
104 cs130_tom  1.5  	if (*sock == INVALID_SOCKET) {
105 cs130_tom  1.4  		WSACleanup();
106                 		exit(0);
107                 	}
108                 
109 cs130_tom  1.5  	addr->sin_family = AF_INET;
110                 	addr->sin_addr.s_addr = INADDR_ANY;
111                 	addr->sin_port = htons(0);
112 cs130_tom  1.4  
113 cs130_tom  1.19 	// bind socket to port
114                 	bindOK = !bind(*sock, (const SOCKADDR *) addr, sizeof(*addr));
115                 	ok( bindOK , "Error binding client to socket");
116                 	if( !bindOK ) {
117 cs130_tom  1.5  		WSACleanup();
118                 		exit(0);
119                 	}
120 cs130_tom  1.4  
121 cs130_tom  1.5  	// get port number
122                 	tmpAddrSize = sizeof(tmpAddr);
123                 	getsockname(*sock, (SOCKADDR *) &tmpAddr, &tmpAddrSize);
124                 	addr->sin_port = tmpAddr.sin_port;
125                 }
126 cs130_tom  1.4  
127 cs130_tom  1.20 void BlockingClient(volatile int *serverPort)
128 cs130_tom  1.5  {
129                 	SOCKET sock;
130 cs130_tom  1.6  	SOCKADDR_IN client, server;
131                 	HOSTENT *hp;
132 cs130_tom  1.16 	int connectError;
133                 	int totCharsReceived = 0;
134                 	int numCharsReceived;
135                 	int memSame;
136 cs130_tom  1.19 	int yieldCounter = 0;
137 cs130_tom  1.16 	char buf[1001];
138 cs130_tom  1.12 
139 cs130_tom  1.5  	StartNetworkApp(SOCK_STREAM, &sock, &client);
140                 
141 cs130_tom  1.20 	//trace("client port %d\n",ntohs(client.sin_port));
142                 
143 cs130_tom  1.6  	hp = gethostbyname("localhost");
144                 
145 cs130_tom  1.19 	// yield until server determines its random port number
146 cs130_tom  1.17 	while(*serverPort == 0)
147 cs130_tom  1.23 		Sleep(100);
148 cs130_tom  1.6  
149                 	server.sin_family = AF_INET;
150                 	server.sin_addr = *(struct in_addr *) hp->h_addr;
151                 	server.sin_port = *serverPort;
152 cs130_tom  1.4  
153 cs130_tom  1.19 	// connect to server
154 cs130_tom  1.16 	connectError = connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr));
155                 	ok( !connectError , "client cannot connect to host\n");
156                 	if(connectError) {
157 cs130_tom  1.12 		WSACleanup();
158                 		exit(0);
159                 	}
160 cs130_tom  1.19 
161                 	// start receiving data from server
162 cs130_tom  1.16 	while( totCharsReceived < TEST_DATA_SIZE ) {
163                 		numCharsReceived = recv(sock, buf, 1000, 0);
164                 		ok( numCharsReceived > 0, "socket was closed unexpectedly" );
165 cs130_tom  1.19 		
166                 		// check received data againt global test data
167 cs130_tom  1.16 		memSame = ! memcmp(buf,testData+totCharsReceived,numCharsReceived);
168 cs130_tom  1.19 		ok( memSame, "data integrity lost during transfer" );
169                 		totCharsReceived += numCharsReceived;
170 cs130_tom  1.18 
171 cs130_tom  1.19 		// yield to our other threads
172                 		if(yieldCounter % 20 == 0) {
173 cs130_tom  1.23 			//Sleep(100);
174 cs130_tom  1.18 		}
175 cs130_tom  1.19 		yieldCounter++;
176 cs130_tom  1.12 	}
177                 
178 cs130_tom  1.22 	//trace("client done\n");
179 cs130_tom  1.7  	clientsDone++;
180 rizwank    1.1  }
181                 
182 cs130_tom  1.17 void ProcessConnection(struct ServerThread *t)
183 cs130_doug 1.8  {
184                 	// this will handle all connections to the server, it's in its own function to allow for multithreading
185 cs130_tom  1.10 	int bClosed;
186 cs130_tom  1.17 	int totCharsSent = 0;
187                 	int numCharsSent;
188 cs130_tom  1.19 	int yieldCounter = 0;
189 cs130_tom  1.17 	const int charsPerSend = 2000;
190                 
191 cs130_tom  1.19 	// loop and send data
192 cs130_tom  1.17 	while( totCharsSent < TEST_DATA_SIZE ) {
193 cs130_tom  1.18 		numCharsSent = send(t->ConnectedSocket, testData+totCharsSent, (totCharsSent + charsPerSend <= TEST_DATA_SIZE) ? charsPerSend : TEST_DATA_SIZE - totCharsSent, 0);
194 cs130_tom  1.19 		ok( numCharsSent != SOCKET_ERROR, "socket error" );
195 cs130_tom  1.17 		if(numCharsSent == SOCKET_ERROR) {
196                 			printf("error code: %d",WSAGetLastError());
197                 		}
198                 		totCharsSent += numCharsSent;
199 cs130_tom  1.19 
200                 		// yield to our other threads
201                 		if(yieldCounter % 20 == 0) {
202 cs130_tom  1.23 			//Sleep(100);
203 cs130_tom  1.19 		}
204                 		yieldCounter++;
205 cs130_tom  1.17 	}
206                 
207 cs130_tom  1.19 	bClosed = !closesocket(t->ConnectedSocket);
208                 	ok(bClosed,"Error closing socket");
209 cs130_doug 1.8  }
210                 
211 cs130_tom  1.20 void BlockingServer(volatile int *port) // listens for incoming connections and accepts up to NUM_CLIENTS connections at once
212 rizwank    1.3  {
213 cs130_tom  1.12 	struct ServerThread *Threads;
214 cs130_doug 1.11 	int ThreadIndex = 0;
215                 
216                 	SOCKET sock;
217                 	SOCKADDR_IN server;
218 cs130_tom  1.12 	int ListenReturn;
219 cs130_tom  1.10 
220 cs130_tom  1.5  	StartNetworkApp(SOCK_STREAM, &sock, &server);
221 cs130_tom  1.9  
222 cs130_tom  1.19 	// allocate enough space to keep track of NUM_CLIENTS connections
223 cs130_tom  1.12 	Threads = malloc(sizeof(struct ServerThread) * NUM_CLIENTS);
224                 	memset(Threads, 0, sizeof(struct ServerThread) * NUM_CLIENTS);
225                 
226 cs130_tom  1.19 	// listen on port
227 cs130_tom  1.17 	ListenReturn = listen(sock, NUM_CLIENTS);
228 cs130_doug 1.11 	ok(ListenReturn != SOCKET_ERROR, "error listening on socket");
229 cs130_tom  1.17 
230 cs130_tom  1.19 	// set the port parameter; clients now know we're ready to accept connections
231 cs130_tom  1.17 	*port = server.sin_port;
232                 
233 cs130_tom  1.23 	// bound to port; now we can start clients
234                 	CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &StartBlockingClients, port, 0, NULL);
235                 
236 cs130_tom  1.19 	// we require one connection from each client thread
237 cs130_tom  1.17 	for (ThreadIndex = 0; ThreadIndex < NUM_CLIENTS; ThreadIndex++) {
238 cs130_tom  1.19 			// accept connection
239 cs130_tom  1.14 			Threads[ThreadIndex].ConnectedSocket = accept(sock, (SOCKADDR *) &Threads[ThreadIndex].Client, &sizeofSOCKADDR_IN); // this can be modified to include the address of the remote socket
240                 			ok(Threads[ThreadIndex].ConnectedSocket != INVALID_SOCKET, "error accepting socket");
241 cs130_tom  1.19 
242                 			// spawn thread to handle sending data
243 cs130_tom  1.17 			Threads[ThreadIndex].ServerThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &ProcessConnection, &Threads[ThreadIndex], 0, &Threads[ThreadIndex].ServerThreadID);
244 cs130_doug 1.8  	}
245 cs130_tom  1.5  
246 cs130_tom  1.19 	// wait for all clients to receive data before cleaning up
247 cs130_tom  1.17 	while (clientsDone != NUM_CLIENTS)
248 cs130_tom  1.23 		Sleep(100);
249 cs130_tom  1.5  
250 cs130_doug 1.13 	free(Threads);
251 rizwank    1.3  }
252                 
253 cs130_tom  1.23 static void StartBlockingClients(volatile int *serverPort)
254 rizwank    1.3  {
255 cs130_tom  1.9  	int ThreadIndex = 0;
256 cs130_tom  1.20 	struct MyThread *ClientThreads;
257 cs130_tom  1.9  
258 cs130_tom  1.20 	ClientThreads = malloc(sizeof(struct MyThread) * NUM_CLIENTS);
259                 	memset(ClientThreads, 0, sizeof(struct MyThread) * NUM_CLIENTS);
260 cs130_tom  1.18 
261 cs130_tom  1.9  	for(ThreadIndex = 0; ThreadIndex < NUM_CLIENTS; ThreadIndex++) {
262 cs130_tom  1.23 		ClientThreads[ThreadIndex].Handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingClient, (void *) serverPort, 0, &ClientThreads[ThreadIndex].ID);
263 cs130_tom  1.9  	}
264 cs130_tom  1.20 	trace("%d clients started\n", NUM_CLIENTS);
265 cs130_tom  1.9  
266 cs130_tom  1.20 	// wait for all clients to receive data before cleaning up
267 cs130_tom  1.19 	while (clientsDone != NUM_CLIENTS)
268 cs130_tom  1.23 		Sleep(100);
269 cs130_tom  1.19 
270                 	free(ClientThreads);
271 cs130_tom  1.23 }
272                 
273                 static void test_ClientServerBlocking_1(void)
274                 {
275                 	// tell the compiler not to optimize code relating to serverPort
276                 	volatile int *serverPort;
277                 	struct MyThread ServerThread;
278                 	
279                 	serverPort = malloc(sizeof(int));
280                 	*serverPort = 0;
281                 
282                 	// start server thread
283                 	// server starts client threads after it binds to a port.
284                 	trace("starting main server thread\n");
285                 	ServerThread.Handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingServer, (void *) serverPort, 0, &ServerThread.ID);
286                 
287                 	// wait for all clients to receive data before cleaning up
288                 	while (clientsDone != NUM_CLIENTS)
289                 		Sleep(100);
290 cs130_tom  1.19 
291 cs130_tom  1.5  	trace("test_ClientServerBlocking_1 done\n");
292 rizwank    1.3  }
293                 
294 cs130_tom  1.4  static void test_Startup(void)
295 rizwank    1.3  {
296 cs130_tom  1.4  	// initialize application
297                 	WSADATA wsaData;
298 cs130_tom  1.22 	int wsastartup_result;
299 cs130_tom  1.14 	int versionOK;
300                 
301 cs130_tom  1.19 	// check for compatible winsock version
302 cs130_tom  1.14 	wsastartup_result = WSAStartup(MAKEWORD(1,1), &wsaData);
303                 	versionOK = (LOBYTE(wsaData.wVersion) == 1) && (HIBYTE(wsaData.wVersion) == 1);
304                 
305                 	ok( versionOK , "WSAStartup returns an incompatible sockets version");
306                 	if ( !versionOK ) {
307 cs130_tom  1.4  		WSACleanup();
308                 		exit(0);
309                 	}
310                 
311 cs130_tom  1.22 	ok((wsastartup_result == NO_ERROR), "Error in WSAStartup()");
312                 	trace("startup ok\n");
313                 }
314                 
315                 
316                 static void test_Cleanup(void)
317                 {
318                 	int cleanupOK;
319                 
320                 	cleanupOK = ! WSACleanup();
321                 
322                 	ok( cleanupOK , "error in WSACleanup()");
323                 	trace("cleanup ok\n");
324 rizwank    1.3  }
325 cs130_tom  1.4  
326 rizwank    1.1  START_TEST(wsock32_main)
327                 {
328 cs130_tom  1.22 	const int numTests = 3;
329 cs130_tom  1.15 	testData = malloc(TEST_DATA_SIZE);
330 cs130_tom  1.22   
331                 	trace("test 1 of %d:\n", numTests);
332                 	test_Startup();
333                   
334                 	trace("test 2 of %d:\n", numTests);
335                 	test_ClientServerBlocking_1();
336                 	
337                 	trace("test 3 of %d:\n", numTests);
338                 	test_Cleanup();
339                 
340 cs130_tom  1.4    trace("all tests done\n");
341 cs130_tom  1.20 
342 cs130_tom  1.19 	free(testData);
343 rizwank    1.1  }

Rizwan Kassim
Powered by
ViewCVS 0.9.2