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

Rizwan Kassim
Powered by
ViewCVS 0.9.2