1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include <vector>
26 #include <cstdlib>
27 #include <ut/ut.h>
28 #include <sock/thread.h>
29 #include <http/http.h>
30 #include <base/result.h>
31
32 static MI_Uint16 PORT = ut::getUnittestPortNumber() + 10;
33
34 using namespace std;
35
36 /*************************************/
37 /* local data */
38 static Http* s_http;
39 static bool s_stop;
40 static ThreadHandle s_t;
41
42 #if defined(_MSC_VER)
43 mike 1.1 #undef BEGIN_EXTERNC
44 #undef END_EXTERNC
45 #define BEGIN_EXTERNC
46 #define END_EXTERNC
47 #endif
48
49 static void setUp()
50 {
51 PORT++;
52 }
53
54 static void cleanup()
55 {
56 }
57 /* helper functions */
58 BEGIN_EXTERNC
59 static void* MI_CALL _HTTPServerProc(void* )
60 {
61 Sock_Start();
62 // pump messages
63 for (; !s_stop; )
64 mike 1.1 Http_Run( s_http, 1000 );
65
66 Sock_Stop();
67 return 0;
68 }
69 END_EXTERNC
70
71 BEGIN_EXTERNC
72 static void _StartHTTP_Server(
73 HttpCallbackOnNewConnection callbackOnNewConnection,
74 HttpCallbackOnCloseConnection callbackOnCloseConnection,
75 HttpCallbackOnRequest callbackOnRequest,
76 void* callbackData,
77 const HttpOptions* options = 0)
78 {
79 /* create a server */
80 UT_ASSERT( MI_RESULT_OK == Http_New_Server(
81 &s_http, 0, PORT, 0,
82 callbackOnNewConnection,
83 callbackOnCloseConnection,
84 callbackOnRequest, callbackData) );
85 mike 1.1
86 if (options)
87 {
88 UT_ASSERT( MI_RESULT_OK == Http_SetOptions(
89 s_http, options) );
90 }
91
92 /* create a thread for message consumption */
93 s_stop = false;
94
95 UT_ASSERT(MI_RESULT_OK == Thread_Create(
96 _HTTPServerProc, 0, &s_t));
97
98 }
99 END_EXTERNC
100
101 BEGIN_EXTERNC
102 static void _StopHTTP_Server()
103 {
104 s_stop = true;
105 UT_ASSERT(MI_RESULT_OK == Thread_Destroy( s_t, MI_TRUE ));
106 mike 1.1 UT_ASSERT( MI_RESULT_OK == Http_Delete(s_http) );
107
108 s_t = 0;
109 s_http = 0;
110 s_stop = false;
111 }
112 END_EXTERNC
113
114 struct ThreadParam
115 {
116 string messageToSend;
117 size_t bytesToSendPerOperation;
118 string response;
119 bool gotRsp;
120 };
121
122 static Sock SockConnectLocal(unsigned short port)
123 {
124 Sock sock;
125 Addr addr;
126 MI_Result r;
127 mike 1.1
128 Sock_Start();
129
130 // Initialize address (connect using loopback).
131 r = Addr_Init(&addr, "127.0.0.1", port);
132 UT_ASSERT(r == MI_RESULT_OK);
133
134 // Create client socket.
135 r = Sock_Create(&sock);
136 UT_ASSERT(r == MI_RESULT_OK);
137
138 r = Sock_Connect(sock, &addr);
139 UT_ASSERT(r == MI_RESULT_OK);
140 return sock;
141 }
142
143 /* simple http client */
144 BEGIN_EXTERNC
145 static void* MI_CALL _http_client_proc(void* param)
146 {
147 ThreadParam* p = (ThreadParam*)param;
148 mike 1.1
149 Sock sock;
150 MI_Result r;
151
152 Sock_Start();
153
154 // Initialize address (connect using loopback).
155 sock = SockConnectLocal(PORT);
156
157 size_t sent = 0;
158 size_t size_left = p->messageToSend.size();
159 const char* buf = p->messageToSend.c_str();
160
161 while ( size_left )
162 {
163 size_t wantToSend = min(p->bytesToSendPerOperation, size_left);
164 r = Sock_Write(sock, buf, wantToSend, &sent);
165
166 //printf("size_left %d, r %d, sent %d, want-send %d\n", size_left, r, sent, wantToSend);
167 if ( r != MI_RESULT_OK)
168 {
169 mike 1.1 printf("size_left %d, r %d, want write %d, sent %d, le %d\n", (int)size_left, (int)r, (int)wantToSend, (int)sent, Sock_GetLastError());
170 ut::sleep_ms( 7000 );
171
172 }
173
174 UT_ASSERT(r == MI_RESULT_OK);
175 // printf("s: %d\n", (int)sent);
176 size_left -= sent;
177 buf += sent;
178 ut::sleep_ms( 1 );
179 }
180
181 // read response
182 char r_buf[1024];
183 size_t read = 0;
184 r = Sock_Read(sock, r_buf, sizeof(r_buf), &read);
185
186
187 if (r) printf("s,r: %d, err %d\n", (int)read, Sock_GetLastError());
188
189 UT_ASSERT(r == MI_RESULT_OK);
190 mike 1.1
191 p->response = string(r_buf, r_buf + read);
192
193 p->gotRsp = true;
194 Sock_Close(sock);
195
196 Sock_Stop();
197 return 0;
198 }
199 END_EXTERNC
200
201 BEGIN_EXTERNC
202 static void* MI_CALL http_client_proc(void* param)
203 {
204 try
205 {
206 return _http_client_proc(param);
207 }
208 catch (ut::UnittestException ex)
209 {
210 ex.m_testcase = "--http_client_proc"; testFailed(ex);
211 mike 1.1 }
212 return 0;
213 }
214 END_EXTERNC
215
216 struct CallbackStruct
217 {
218 string contentType;
219 string charset;
220 string authorization;
221 string username;
222 string password;
223 size_t contentLength;
224 string data;
225 string response;
226
227 CallbackStruct() : contentLength(0){}
228 };
229
230 BEGIN_EXTERNC
231 static void _HttpCallbackOnNewConnection(
232 mike 1.1 Http* /*http*/,
233 void* /*callbackData*/,
234 void* httpConnectionHandle,
235 void** connectionData)
236 {
237 *connectionData = httpConnectionHandle;
238 }
239 END_EXTERNC
240
241 BEGIN_EXTERNC
242 static void _HttpCallbackOnCloseConnection(
243 Http* /*http*/,
244 void* /*callbackData*/,
245 void* /*connectionData*/)
246 {
247 }
248 END_EXTERNC
249
250 BEGIN_EXTERNC
251 static void _HttpCallbackOnRequest(
252 Http* http,
253 mike 1.1 void* callbackData,
254 void* connectionData,
255 void* httpConnectionHandle,
256 const HttpHeaders* headers,
257 Page** page)
258 {
259 CallbackStruct* data = (CallbackStruct*)callbackData;
260
261 UT_ASSERT(httpConnectionHandle == connectionData);
262
263 // printf("cbt, %s\n", headers->authorization);
264
265 if (headers->contentType)
266 data->contentType = headers->contentType;
267
268 if (headers->charset)
269 data->charset = headers->charset;
270
271 if (headers->authorization)
272 data->authorization = headers->authorization;
273 if (headers->username)
274 mike 1.1 data->username = headers->username;
275 if (headers->password)
276 data->password = headers->password;
277
278 data->contentLength = headers->contentLength;
279
280 data->data = string( (char*) ((*page)+1), ((char*)((*page)+1)) + (*page)->u.s.size);
281
282 Page* rsp = (Page*)malloc(sizeof(Page) + data->response.size());
283
284 UT_ASSERT(rsp);
285
286 rsp->u.s.size = data->response.size();
287 memcpy(rsp+1, data->response.c_str(), data->response.size());
288
289 Http_SendResponse( http, httpConnectionHandle, HTTP_ERROR_CODE_OK, &rsp );
290
291 if (rsp )
292 free(rsp);
293 }
294 END_EXTERNC
295 mike 1.1
296 static void TestHttpHappyPass()
297 {
298 Http* http = 0;
299 CallbackStruct cb;
300
301 cb.response = "Response";
302
303 /* create a server */
304 UT_ASSERT( MI_RESULT_OK == Http_New_Server(
305 &http, 0, PORT, 0,
306 _HttpCallbackOnNewConnection,
307 _HttpCallbackOnCloseConnection,
308 _HttpCallbackOnRequest, &cb) );
309
310
311 /* create a client */
312 ThreadParam param;
313 ThreadHandle t;
314
315 param.messageToSend =
316 mike 1.1 "POST /wsman HTTP/1.1\r\n"
317 "Content-Type: application/soap+xml;charset=UTF-8\r\n"
318 "User-Agent: Microsoft WinRM Client\r\n"
319 "Host: localhost:7778\r\n"
320 "Content-Length: 5\r\n"
321 "Authorization: auth\r\n"
322 "\r\n"
323 "Hello";
324 param.bytesToSendPerOperation = 30000;
325 param.gotRsp = false;
326
327 UT_ASSERT(MI_RESULT_OK == Thread_Create(
328 http_client_proc, ¶m, &t));
329
330
331 // pump messages
332 for (int i = 0; !param.gotRsp && i < 10000; i++ )
333 Http_Run( http, 1000 );
334
335 // wait for completion and check that
336 UT_ASSERT(MI_RESULT_OK == Thread_Destroy( t, MI_TRUE ));
337 mike 1.1
338
339 // check messages
340 // printf("cb.auth is %s\n", cb.authorization.c_str());
341
342 UT_ASSERT( cb.authorization == "auth" );
343 UT_ASSERT( cb.contentType == "application/soap+xml" );
344 UT_ASSERT( cb.charset == "UTF-8" );
345 UT_ASSERT( cb.contentLength == 5 );
346 UT_ASSERT( cb.data == "Hello" );
347
348 //UT_ASSERT( param.response.find("Response") != string::npos );
349
350 UT_ASSERT( MI_RESULT_OK == Http_Delete(http) );
351 }
352
353 static void TestHttp_BigLoad()
354 {
355 Http* http = 0;
356 CallbackStruct cb;
357
358 mike 1.1 cb.response = string(256 * 1024, '*');
359
360
361 /* create a server */
362 UT_ASSERT( MI_RESULT_OK == Http_New_Server(
363 &http, 0, PORT, 0,
364 _HttpCallbackOnNewConnection,
365 _HttpCallbackOnCloseConnection,
366 _HttpCallbackOnRequest, &cb) );
367
368
369 /* create a client */
370 ThreadParam param;
371 ThreadHandle t;
372
373 param.messageToSend =
374 "POST /wsman HTTP/1.1\r\n"
375 "Content-Type: text\r\n"
376 "User-Agent: Microsoft WinRM Client\r\n"
377 "Host: localhost:7778\r\n"
378 "Content-Length: 32999\r\n"
379 mike 1.1 "Authorization: auth\r\n"
380 "\r\n";
381
382 param.messageToSend += string(32999, '.');
383
384 param.bytesToSendPerOperation = 8000;
385 param.gotRsp = false;
386
387 UT_ASSERT(MI_RESULT_OK == Thread_Create(
388 http_client_proc, ¶m, &t));
389
390
391 // pump messages
392 for (int i = 0; !param.gotRsp && i < 10000; i++ )
393 Http_Run( http, 1000 );
394
395 //printf("out of run\n");
396
397 // wait for completion and check that
398 UT_ASSERT(MI_RESULT_OK == Thread_Destroy( t, MI_TRUE ));
399
400 mike 1.1
401 // check messages
402 // printf("cb.auth is %s\n", cb.authorization.c_str());
403
404 UT_ASSERT( cb.authorization == "auth" );
405 UT_ASSERT( cb.password == "" );
406 UT_ASSERT( cb.username == "" );
407 UT_ASSERT( cb.contentType == "text" );
408 UT_ASSERT( cb.charset == "" );
409 UT_ASSERT( cb.contentLength == 32999 );
410 UT_ASSERT( cb.data == string(32999, '.') );
411
412 //UT_ASSERT( param.response.find("Response") != string::npos );
413
414 UT_ASSERT( MI_RESULT_OK == Http_Delete(http) );
415 }
416
417 static void TestHttp_QuotedCharset()
418 {
419 Http* http = 0;
420 CallbackStruct cb;
421 mike 1.1
422 cb.response = "Response";
423
424 /* create a server */
425 UT_ASSERT( MI_RESULT_OK == Http_New_Server(
426 &http, 0, PORT, 0,
427 _HttpCallbackOnNewConnection,
428 _HttpCallbackOnCloseConnection,
429 _HttpCallbackOnRequest, &cb) );
430
431
432 /* create a client */
433 ThreadParam param;
434 ThreadHandle t;
435
436 param.messageToSend =
437 "POST /wsman HTTP/1.1\r\n"
438 "Content-Type: application/soap+xml; \tcharset=\"UTF-16\"\t \r\n"
439 "User-Agent: Microsoft WinRM Client\r\n"
440 "Host: localhost:7778\r\n"
441 "Content-Length: 5\r\n"
442 mike 1.1 "Authorization: auth\r\n"
443 "\r\n"
444 "aloha";
445 param.bytesToSendPerOperation = 30000;
446 param.gotRsp = false;
447
448 UT_ASSERT(MI_RESULT_OK == Thread_Create(
449 http_client_proc, ¶m, &t));
450
451
452 // pump messages
453 for (int i = 0; !param.gotRsp && i < 10000; i++ )
454 Http_Run( http, 1000 );
455
456 // wait for completion and check that
457 UT_ASSERT(MI_RESULT_OK == Thread_Destroy( t, MI_TRUE ));
458
459
460 // check messages
461 // printf("cb.auth is %s\n", cb.authorization.c_str());
462
463 mike 1.1 UT_ASSERT( cb.authorization == "auth" );
464 UT_ASSERT( cb.contentType == "application/soap+xml" );
465 UT_ASSERT( cb.charset == "UTF-16" );
466 UT_ASSERT( cb.contentLength == 5 );
467 UT_ASSERT( cb.data == "aloha" );
468
469 //UT_ASSERT( param.response.find("Response") != string::npos );
470
471 UT_ASSERT( MI_RESULT_OK == Http_Delete(http) );
472 }
473
474 static void TestHttp_Base64Decoding()
475 {
476 Http* http = 0;
477 CallbackStruct cb;
478
479 cb.response = "Response";
480
481 /* create a server */
482 UT_ASSERT( MI_RESULT_OK == Http_New_Server(
483 &http, 0, PORT, 0,
484 mike 1.1 _HttpCallbackOnNewConnection,
485 _HttpCallbackOnCloseConnection,
486 _HttpCallbackOnRequest, &cb) );
487
488
489 /* create a client */
490 ThreadParam param;
491 ThreadHandle t;
492
493 param.messageToSend =
494 "POST /wsman HTTP/1.1\r\n"
495 "Content-Type: application/soap+xml; \tcharset=\"UTF-16\"\t \r\n"
496 "User-Agent: Microsoft WinRM Client\r\n"
497 "Host: localhost:7778\r\n"
498 "Content-Length: 5\r\n"
499 "Authorization: Basic \t \tcm9vdDpPcHNNZ3IyMDA3UjI=\t \r\n"
500 "\r\n"
501 "aloha";
502 param.bytesToSendPerOperation = 30000;
503 param.gotRsp = false;
504
505 mike 1.1 UT_ASSERT(MI_RESULT_OK == Thread_Create(
506 http_client_proc, ¶m, &t));
507
508
509 // pump messages
510 for (int i = 0; !param.gotRsp && i < 10000; i++ )
511 Http_Run( http, 1000 );
512
513 // wait for completion and check that
514 UT_ASSERT(MI_RESULT_OK == Thread_Destroy( t, MI_TRUE ));
515
516
517 // check messages
518 // printf("cb.auth is %s\n", cb.authorization.c_str());
519
520 UT_ASSERT( cb.authorization == "" );
521 UT_ASSERT( cb.username == "root" );
522 UT_ASSERT( cb.password == "OpsMgr2007R2" );
523 UT_ASSERT( cb.contentType == "application/soap+xml" );
524 UT_ASSERT( cb.charset == "UTF-16" );
525 UT_ASSERT( cb.contentLength == 5 );
526 mike 1.1 UT_ASSERT( cb.data == "aloha" );
527
528 //UT_ASSERT( param.response.find("Response") != string::npos );
529
530 UT_ASSERT( MI_RESULT_OK == Http_Delete(http) );
531 }
532
533 static void TestHttp_InvalidBase64Data()
534 {
535 Http* http = 0;
536 CallbackStruct cb;
537
538 cb.response = "Response";
539
540 /* create a server */
541 UT_ASSERT( MI_RESULT_OK == Http_New_Server(
542 &http, 0, PORT, 0,
543 _HttpCallbackOnNewConnection,
544 _HttpCallbackOnCloseConnection,
545 _HttpCallbackOnRequest, &cb) );
546
547 mike 1.1
548 /* create a client */
549 ThreadParam param;
550 ThreadHandle t;
551
552 /* send request with invalid base64 data; server should close connection */
553 param.messageToSend =
554 "POST /wsman HTTP/1.1\r\n"
555 "Content-Type: application/soap+xml; \tcharset=\"UTF-16\"\t \r\n"
556 "User-Agent: Microsoft WinRM Client\r\n"
557 "Host: localhost:7778\r\n"
558 "Content-Length: 5\r\n"
559 "Authorization: Basic \t \tcm9vd\xFE\xFF==\t \r\n"
560 "\r\n"
561 "aloha";
562 param.bytesToSendPerOperation = 30000;
563 param.gotRsp = false;
564
565 UT_ASSERT(MI_RESULT_OK == Thread_Create(
566 http_client_proc, ¶m, &t));
567
568 mike 1.1
569 // pump messages
570 for (int i = 0; !param.gotRsp && i < 10000; i++ )
571 Http_Run( http, 1000 );
572
573 // wait for completion and check that
574 UT_ASSERT(MI_RESULT_OK == Thread_Destroy( t, MI_TRUE ));
575
576
577 // check messages
578 // printf("cb.auth is %s\n", cb.authorization.c_str());
579 UT_ASSERT( param.response.empty() );
580
581 UT_ASSERT( cb.authorization == "" );
582 UT_ASSERT( cb.username == "" );
583 UT_ASSERT( cb.password == "" );
584 UT_ASSERT( cb.contentType == "" );
585 UT_ASSERT( cb.charset == "" );
586 UT_ASSERT( cb.contentLength == 0 );
587 UT_ASSERT( cb.data == "" );
588
589 mike 1.1 UT_ASSERT( MI_RESULT_OK == Http_Delete(http) );
590 }
591
592 BEGIN_EXTERNC
593 static void _HttpCallbackOnRequest_NeverCalled(
594 Http* ,
595 void* ,
596 void* ,
597 void* ,
598 const HttpHeaders* ,
599 Page** )
600 {
601 UT_ASSERT_FAILED_MSG("should be never called");
602 }
603 END_EXTERNC
604
605 BEGIN_EXTERNC
606 static void _ConnectToServerExpectConnectionDrop(const string& data, MI_Uint32 sleepInsideSendMS)
607 {
608 Sock sock;
609 MI_Result r;
610 mike 1.1
611 // Initialize address (connect using loopback).
612 sock = SockConnectLocal(PORT);
613
614 size_t sent = 0;
615 size_t size_left = data.size();
616 const char* buf = data.c_str();
617
618 while ( size_left )
619 {
620 size_t wantToSend = size_left;
621
622 /* send all but last bytes; sleep before sending last byte */
623 if (wantToSend > 1)
624 {
625 wantToSend--;
626 }
627 else
628 {
629 /* sleep before sending last byte */
630 ut::sleep_ms(sleepInsideSendMS);
631 mike 1.1 }
632
633 r = Sock_Write(sock, buf, wantToSend, &sent);
634
635 //if (r != MI_RESULT_OK)
636 //printf("errno %d\n", errno);
637
638 UT_ASSERT(r == MI_RESULT_OK ||
639 (r == MI_RESULT_FAILED && 1 == wantToSend) );
640 //printf("s: %d\n", (int)sent);
641
642 if (0 == sent)
643 break;
644
645 size_left -= sent;
646 buf += sent;
647 }
648
649
650 if (sent != 0)
651 {
652 mike 1.1 // read response
653 char r_buf[1024];
654 size_t read = 0;
655 r = Sock_Read(sock, r_buf, sizeof(r_buf), &read);
656 //printf("s,r: %d, res = %d\n", (int)read, (int)r);
657
658 UT_ASSERT(r == MI_RESULT_OK || r == MI_RESULT_FAILED);
659 UT_ASSERT(read == 0);
660 }
661
662 Sock_Close(sock);
663 }
664 END_EXTERNC
665
666
667 static void TestHttp_HeaderTooBig()
668 {
669 // send huge http header and expecting connection to be dropped
670 _StartHTTP_Server(
671 _HttpCallbackOnNewConnection,
672 _HttpCallbackOnCloseConnection,
673 mike 1.1 _HttpCallbackOnRequest_NeverCalled,
674 0);
675
676 string data =
677 "POST /wsman HTTP/1.1\r\n"
678 "Content-Type: ct\r\n"
679 "User-Agent: Microsoft WinRM Client\r\n"
680 "Host: localhost:7778\r\n"
681 "Content-Length: 5\r\n"
682 "Authorization: auth\r\n";
683
684 data += string("hugeAttribute: ") + string(4096, 'x') + string("\r\n");
685 data += "\r\n"
686 "Hello";
687
688 _ConnectToServerExpectConnectionDrop(data, 0);
689
690 _StopHTTP_Server();
691 }
692
693 static void TestHttp_TimeoutMidPacket()
694 mike 1.1 {
695 HttpOptions options = {1000}; /* 1 ms */
696
697 // send http header with delay in the middle of the package and expecting connection to be dropped
698 _StartHTTP_Server(
699 _HttpCallbackOnNewConnection,
700 _HttpCallbackOnCloseConnection,
701 _HttpCallbackOnRequest_NeverCalled,
702 0,
703 &options);
704
705 string data =
706 "POST /wsman HTTP/1.1\r\n"
707 "Content-Type: ct\r\n"
708 "User-Agent: Microsoft WinRM Client\r\n"
709 "Host: localhost:7778\r\n"
710 "Content-Length: 5\r\n"
711 "Authorization: auth\r\n"
712 "\r\n"
713 "Hello";
714
715 mike 1.1 _ConnectToServerExpectConnectionDrop(data, 100);
716
717 _StopHTTP_Server();
718 }
719
720 static void TestHttp_LongContent()
721 {
722 HttpOptions options = {1000}; /* 1 ms */
723
724 // send http header with delay in the middle of the package and expecting connection to be dropped
725 _StartHTTP_Server(
726 _HttpCallbackOnNewConnection,
727 _HttpCallbackOnCloseConnection,
728 _HttpCallbackOnRequest_NeverCalled,
729 0,
730 &options);
731
732 string data =
733 "POST /wsman HTTP/1.1\r\n"
734 "Content-Type: ct\r\n"
735 "User-Agent: Microsoft WinRM Client\r\n"
736 mike 1.1 "Host: localhost:7778\r\n"
737 "Content-Length: 5\r\n"
738 "Authorization: auth\r\n"
739 "\r\n"
740 "Hello (this part of the message is not accounted for n content-length and may cause buffer overrun)";
741
742 _ConnectToServerExpectConnectionDrop(data, 100);
743
744 _StopHTTP_Server();
745 }
746
747
748 static void RunTests()
749 {
750 Sock_Start();
751
752 UT_TEST(TestHttp_BigLoad);
753 UT_TEST(TestHttpHappyPass);
754 UT_TEST(TestHttp_QuotedCharset);
755 UT_TEST(TestHttp_Base64Decoding);
756 UT_TEST(TestHttp_HeaderTooBig);
757 mike 1.1 UT_TEST(TestHttp_TimeoutMidPacket);
758 UT_TEST(TestHttp_InvalidBase64Data);
759 UT_TEST(TestHttp_LongContent);
760
761 Sock_Stop();
762 }
763
764 UT_ENTRY_POINT(RunTests);
|