Simulated product dispenser
Fork of mbed-cloud-workshop-connect-HTS221 by
pal_socket_test.c
00001 /******************************************************************************* 00002 * Copyright 2016, 2017 ARM Ltd. 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 *******************************************************************************/ 00016 00017 #include "pal.h" 00018 #include "pal_network.h" 00019 #include "unity.h" 00020 #include "unity_fixture.h" 00021 #include "PlatIncludes.h" 00022 #include "pal_BSP.h" 00023 #include "string.h" 00024 00025 #ifdef __LINUX__ 00026 #include <netdb.h> 00027 #define test_getAddressInfo getAddressInfoIPv4 00028 #else 00029 #define test_getAddressInfo pal_getAddressInfo 00030 #endif 00031 00032 TEST_GROUP(pal_socket); 00033 00034 //Sometimes you may want to get local data in a module, 00035 //for example if you need to pass a reference. 00036 //However, you should usually avoid this. 00037 //extern int Counter; 00038 00039 #define PAL_NET_SUPPORT_LWIP 1 00040 #define PAL_NET_TEST_SERVER_NAME "www.arm.com" 00041 #define PAL_NET_TEST_SERVER_NAME_UDP "8.8.8.8" 00042 #define PAL_TEST_KEEPALIVE_SERVER_ADDRESS "62.44.193.186" 00043 #define PAL_TEST_KEEPALIVE_NUM_OF_ACK 4 00044 00045 #define PAL_NET_TEST_SERVER_HTTP_PORT 80 00046 #define PAL_TEST_SERVER_KEEPALIVE_PORT 5533 00047 00048 #define PAL_NET_TEST_SERVER_UDP_PORT 53 00049 #define PAL_NET_TEST_INCOMING_PORT 8002 00050 #define PAL_NET_TEST_INCOMING_PORT2 8989 00051 00052 #define PAL_NET_TEST_LOCAL_LOOPBACK_IF_INDEX 0 00053 extern void * g_palTestNetworkInterface; // this is set by the palTestMain funciton 00054 PAL_PRIVATE uint32_t g_interfaceCTXIndex = 0; 00055 PAL_PRIVATE uint32_t s_callbackcounter = 0; 00056 00057 #define PAL_NET_TEST_SOCKETS 4 00058 PAL_PRIVATE palSocket_t g_testSockets[PAL_NET_TEST_SOCKETS] = {0,0,0,0}; 00059 00060 #define PAL_NET_TEST_GOOGLE_CDN_HOST "ajax.googleapis.com" /*! CDN host server */ 00061 #define PAL_NET_TEST_GOOGLE_CDN_HOST_PORT 80 /*! CDN host port */ 00062 #define PAL_NET_TEST_GOOGLE_CDN_REQUEST "GET /ajax/libs/jquery/3.2.1/jquery.js HTTP/1.0\r\nHost:" PAL_NET_TEST_GOOGLE_CDN_HOST "\r\n\r\n" /*! HTTP get request */ 00063 #define PAL_NET_TEST_BUFFERED_TCP_BUF_SIZE_SMALL 4 00064 #define PAL_NET_TEST_BUFFERED_TCP_BUF_SIZE_LARGE 1024 00065 #define PAL_NET_TEST_BUFFERED_UDP_BUF_SIZE_SMALL 64 00066 #define PAL_NET_TEST_BUFFERED_UDP_BUF_SIZE_LARGE 512 00067 #define PAL_NET_TEST_BUFFERED_UDP_PORT 2606 00068 #define PAL_NET_TEST_BUFFERED_UDP_MESSAGE_SIZE (1024 * 256) 00069 PAL_PRIVATE uint8_t *g_testRecvBuffer = NULLPTR; 00070 PAL_PRIVATE uint8_t *g_testSendBuffer = NULLPTR; 00071 00072 typedef struct pal_udp_test_data /*! structure used to hold state in UDP buffered tests */ 00073 { 00074 const size_t messageSize; 00075 const size_t bufferSize; 00076 const uint8_t startValue; 00077 palNetInterfaceInfo_t interfaceInfo; 00078 uint8_t currentValue; 00079 size_t totalSize; 00080 size_t chunkSize; 00081 } pal_udp_test_data_t; 00082 00083 TEST_SETUP(pal_socket) 00084 { 00085 uint32_t i = 0; 00086 palStatus_t status = PAL_SUCCESS; 00087 //This is run before *each test* 00088 pal_init(); 00089 if ( NULL == g_palTestNetworkInterface ) 00090 { 00091 PAL_LOG(ERR, "error: net interface not configutred correctly"); 00092 } 00093 else 00094 { 00095 status = pal_registerNetworkInterface(g_palTestNetworkInterface, &g_interfaceCTXIndex); 00096 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 00097 } 00098 00099 for (i = 0; i < PAL_NET_TEST_SOCKETS; i++) 00100 { 00101 g_testSockets[i] = 0; 00102 } 00103 } 00104 00105 TEST_TEAR_DOWN(pal_socket) 00106 { 00107 uint32_t i = 0; 00108 for (i = 0; i < PAL_NET_TEST_SOCKETS; i++) 00109 { 00110 if (g_testSockets[i] != 0) 00111 { 00112 pal_close(&(g_testSockets[i])); 00113 } 00114 } 00115 00116 if (g_testRecvBuffer != NULLPTR) 00117 { 00118 free(g_testRecvBuffer); 00119 g_testRecvBuffer = NULLPTR; 00120 } 00121 if (g_testSendBuffer != NULLPTR) 00122 { 00123 free(g_testSendBuffer); 00124 g_testSendBuffer = NULLPTR; 00125 } 00126 00127 pal_destroy(); 00128 } 00129 00130 #define PAL_TEST_BUFFER_SIZE 50 00131 PAL_PRIVATE void socketCallback1( void * arg) 00132 { 00133 s_callbackcounter++; 00134 } 00135 00136 /*! \brief Test socket creation, destruction and modification, as well as getting address infromation and checking the blocking status of sockets. 00137 * 00138 ** \test 00139 * | # | Step | Expected | 00140 * |---|--------------------------------|-------------| 00141 * | 1 | Register a net interface using `pal_registerNetworkInterface`. | PAL_SUCCESS | 00142 * | 2 | Register a net interface using `pal_registerNetworkInterface`, and check that the ID is the same as the previous step. | PAL_SUCCESS | 00143 * | 3 | Get the interface address using `pal_getNetInterfaceInfo`. | PAL_SUCCESS | 00144 * | 4 | Create a blocking UDP socket using `pal_socket`. | PAL_SUCCESS | 00145 * | 5 | Create a blocking UDP socket using `pal_socket`. | PAL_SUCCESS | 00146 * | 6 | Create a non-blocking UDP socket using `pal_socket`. | PAL_SUCCESS | 00147 * | 7 | Create a blocking asynchronous TCP socket with `socketCallback1` as callback. | PAL_SUCCESS | 00148 * | 8 | Check the number of net interfaces registered using `pal_getNetInterfaceInfo`. | PAL_SUCCESS | 00149 * | 9 | Set the socket receive timeout using `pal_setSocketOptions`. | PAL_SUCCESS | 00150 * | 10 | Check that the sockets return the correct blocking status using `pal_isNonBlocking`. | PAL_SUCCESS | 00151 * | 11 | Check the `pal_getAddressInfo` function with an invalid address. | PAL_ERR_SOCKET_DNS_ERROR | 00152 * | 12 | Close all sockets. | PAL_SUCCESS | 00153 */ 00154 TEST(pal_socket, socketUDPCreationOptionsTest) 00155 { 00156 palStatus_t result = PAL_SUCCESS; 00157 uint32_t numInterface = 0; 00158 palNetInterfaceInfo_t interfaceInfo; 00159 uint32_t interfaceIndex = 0; 00160 uint32_t interfaceIndex2 = 0; 00161 uint32_t sockOptVal = 5000; 00162 uint32_t sockOptLen = sizeof(sockOptVal); 00163 palSocketAddress_t address = { 0 }; 00164 palSocketLength_t addrlen = 0; 00165 bool isNonBlocking = false; 00166 00167 memset(&interfaceInfo,0,sizeof(interfaceInfo)); 00168 // Check that re-adding the network interface returns the same index 00169 /*#1*/ 00170 result = pal_registerNetworkInterface(g_palTestNetworkInterface, &interfaceIndex); 00171 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00172 00173 /*#2*/ 00174 result = pal_registerNetworkInterface(g_palTestNetworkInterface, &interfaceIndex2); 00175 TEST_ASSERT_EQUAL_HEX(interfaceIndex, interfaceIndex2); 00176 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00177 00178 #if PAL_SUPPORT_IP_V4 00179 /*#3*/ 00180 result = pal_getNetInterfaceInfo(interfaceIndex, &interfaceInfo); 00181 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00182 PAL_PRINTF("Default interface address: %u %u %u %u \r\n", 00183 (unsigned char)interfaceInfo.address.addressData[2], 00184 (unsigned char)interfaceInfo.address.addressData[3], 00185 (unsigned char)interfaceInfo.address.addressData[4], 00186 (unsigned char)interfaceInfo.address.addressData[5]);; 00187 #endif 00188 00189 //Blocking 00190 /*#4*/ 00191 result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM , false, interfaceIndex, &g_testSockets[0]); 00192 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00193 /*#5*/ 00194 result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM , false, interfaceIndex, &g_testSockets[1]); 00195 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00196 //Non-blocking 00197 /*#6*/ 00198 result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM , true, interfaceIndex, &g_testSockets[3]); 00199 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00200 #if PAL_NET_ASYNCHRONOUS_SOCKET_API 00201 /*#7*/ 00202 result = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_STREAM, false, interfaceIndex, socketCallback1, &g_testSockets[2]); 00203 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00204 #endif // PAL_NET_ASYNCHRONOUS_SOCKET_API 00205 00206 /*#8*/ 00207 result = pal_getNumberOfNetInterfaces(&numInterface); 00208 TEST_ASSERT_NOT_EQUAL(numInterface, 0); 00209 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00210 00211 /*#9*/ 00212 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO , &sockOptVal, sockOptLen); 00213 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00214 00215 /*#10*/ 00216 result = pal_isNonBlocking(g_testSockets[0],&isNonBlocking); 00217 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00218 TEST_ASSERT_EQUAL_HEX(isNonBlocking, false); 00219 00220 result = pal_isNonBlocking(g_testSockets[3], &isNonBlocking); 00221 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00222 TEST_ASSERT_EQUAL_HEX(isNonBlocking, true); 00223 00224 /*#11*/ 00225 result = pal_getAddressInfo("0.0.0.0", &address, &addrlen); 00226 TEST_ASSERT_EQUAL_HEX(PAL_ERR_SOCKET_DNS_ERROR , result); 00227 00228 /*#12*/ 00229 #if PAL_NET_ASYNCHRONOUS_SOCKET_API 00230 result = pal_close(&g_testSockets[2]); 00231 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00232 00233 #endif // PAL_NET_ASYNCHRONOUS_SOCKET_API 00234 00235 result = pal_close(&g_testSockets[0]); 00236 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00237 result = pal_close(&g_testSockets[1]); 00238 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00239 result = pal_close(&g_testSockets[3]); 00240 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00241 result = pal_close(&g_testSockets[3]); //double close - should succeed 00242 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00243 } 00244 00245 00246 /*! \brief Test TCP socket creation, connection, send and receive with a test server. 00247 * 00248 ** \test 00249 * | # | Step | Expected | 00250 * |---|--------------------------------|-------------| 00251 * | 1 | Create a blocking TCP socket using `pal_socket`. | PAL_SUCCESS | 00252 * | 2 | Look up the IP address of the test server using `pal_getAddressInfo`. | PAL_SUCCESS | 00253 * | 3 | Set the port to a test port in the address structure using `pal_setSockAddrPort` and set timeout. | PAL_SUCCESS | 00254 * | 4 | Connect the socket to the test server using `pal_connect`. | PAL_SUCCESS | 00255 * | 5 | Send a test message (short HTTP request) to the test server using `pal_send`. | PAL_SUCCESS | 00256 * | 6 | Receive (blocking) the server's response using `pal_recv` and check it is HTTP. | PAL_SUCCESS | 00257 * | 7 | Close the socket. | PAL_SUCCESS | 00258 */ 00259 TEST(pal_socket, basicTCPclientSendRecieve) 00260 { 00261 palStatus_t result = PAL_SUCCESS; 00262 palSocketAddress_t address = { 0 }; 00263 const char message[] = "GET / HTTP/1.0\r\n\r\n"; 00264 size_t sent = 0; 00265 char buffer[100] = { 0 }; 00266 size_t read = 0; 00267 palSocketLength_t addrlen = 0; 00268 int timeout = PAL_MILLI_PER_SECOND; 00269 00270 /*#1*/ 00271 00272 result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_testSockets[0]); 00273 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00274 00275 /*#2*/ 00276 result = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME, &address, &addrlen); 00277 if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result)) 00278 { 00279 PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)"); 00280 goto end; 00281 } 00282 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00283 00284 /*#3*/ 00285 result = pal_setSockAddrPort(&address, PAL_NET_TEST_SERVER_HTTP_PORT); 00286 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00287 00288 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_SNDTIMEO , &timeout, sizeof(timeout)); 00289 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00290 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO , &timeout, sizeof(timeout)); 00291 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00292 00293 00294 /*#4*/ 00295 result = pal_connect(g_testSockets[0], &address, 16); 00296 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00297 00298 /*#5*/ 00299 result = pal_send(g_testSockets[0], message, sizeof(message) - 1, &sent); 00300 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00301 00302 /*#6*/ 00303 result = pal_recv(g_testSockets[0], buffer, 99, &read); 00304 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00305 00306 TEST_ASSERT(read >= 4); 00307 TEST_ASSERT(buffer[0] == 'H' && buffer[1] == 'T'&& buffer[2] == 'T' && buffer[3] == 'P'); 00308 00309 end: //unified cleanup 00310 /*#7*/ 00311 pal_close(&g_testSockets[0]); 00312 00313 } 00314 00315 /*! \brief Test UDP socket creation, connection, send and recieve with a test server. 00316 * 00317 ** \test 00318 * | # | Step | Expected | 00319 * |---|--------------------------------|-------------| 00320 * | 1 | Create a blocking UDP socket using `pal_socket`. | PAL_SUCCESS | 00321 * | 2 | Look up the IP address of the test server using `pal_getAddressInfo`. | PAL_SUCCESS | 00322 * | 3 | Set the port to a test port in the address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 00323 * | 4 | Connect the socket to the test server using `pal_connect`. | PAL_SUCCESS | 00324 * | 5 | Send a test message (short DNS request) to the test server using `pal_send`. | PAL_SUCCESS | 00325 * | 6 | Receive (blocking) the server's response using `pal_recv`. | PAL_SUCCESS | 00326 * | 7 | Close the socket. | PAL_SUCCESS | 00327 */ 00328 TEST(pal_socket, basicUDPclientSendRecieve) 00329 { 00330 palStatus_t result = PAL_SUCCESS; 00331 palSocketAddress_t address = { 0 }; 00332 palSocketAddress_t address2 = { 0 }; 00333 uint8_t buffer[33] = { 0x8e, 0xde, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x61, 0x72, 0x73, 0x74, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x63, 0x61, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 }; 00334 uint8_t buffer_in[10]; 00335 size_t sent = 0; 00336 size_t read = 0; 00337 size_t socket_timeout_ms = 5000; 00338 palSocketLength_t addrlen = 0; 00339 00340 /*#1*/ 00341 result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM , false, 0, &g_testSockets[0]); 00342 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00343 00344 /*#2*/ 00345 result = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME_UDP, &address, &addrlen); 00346 if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result)) 00347 { 00348 PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration can't continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)"); 00349 goto end; 00350 } 00351 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00352 00353 /*#3*/ 00354 result = pal_setSockAddrPort(&address, PAL_NET_TEST_SERVER_UDP_PORT); 00355 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00356 00357 /*#4*/ 00358 //We set a timeout for receiving so we won't get stuck in the test 00359 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO , &socket_timeout_ms, sizeof(socket_timeout_ms)); 00360 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00361 00362 /*#5*/ 00363 result = pal_sendTo(g_testSockets[0], buffer, sizeof(buffer), &address, 16, &sent); 00364 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00365 TEST_ASSERT_EQUAL(sent, sizeof(buffer)); 00366 00367 /*#6*/ 00368 result = pal_receiveFrom(g_testSockets[0], buffer_in, 10, &address2, &addrlen, &read); 00369 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00370 TEST_ASSERT_EQUAL(read, 10); 00371 end: 00372 /*#7*/ 00373 pal_close(&g_testSockets[0]); 00374 } 00375 00376 00377 00378 00379 // This is an example showing how to check for a socket that has been closed remotely. 00380 #if 0 00381 PAL_PRIVATE void basicSocketScenario3Callback(void * arg) 00382 { 00383 char buffer[400]; 00384 size_t read = 0; 00385 palStatus_t result; 00386 00387 00388 s_callbackcounter++; 00389 result = pal_recv(g_testSockets[0], buffer, 999, &read); 00390 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00391 // If 0 bytes are read it means that the peer has performed an orderly shutdown so we must close the socket 00392 // to avoid ppoll from checking it. Checking a socket whose other end has been shut down causes ppoll to immediately return 00393 // with events == 0x1. 00394 if(read == 0) 00395 { 00396 pal_close(&g_testSockets[0]); 00397 } 00398 else 00399 { 00400 buffer[read] = '\0'; 00401 if(s_callbackcounter == 0) 00402 { 00403 TEST_ASSERT(read >= 4); 00404 TEST_ASSERT(buffer[0] == 'H' && buffer[1] == 'T'&& buffer[2] == 'T' && buffer[3] == 'P'); 00405 } 00406 } 00407 00408 } 00409 #endif 00410 palSemaphoreID_t s_semaphoreID = NULLPTR; 00411 00412 PAL_PRIVATE void socketCallback2(void * arg) 00413 { 00414 palStatus_t result; 00415 if(s_callbackcounter == 0) 00416 { 00417 result = pal_osSemaphoreRelease(s_semaphoreID); 00418 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00419 } 00420 s_callbackcounter++; 00421 00422 } 00423 00424 static int s_secondCallbackCounter = 0; 00425 PAL_PRIVATE void socketCallbackErr(void * arg) 00426 { 00427 s_secondCallbackCounter++; 00428 } 00429 00430 /*! \brief Test asynchronous socket callbacks. 00431 * 00432 ** \test 00433 * | # | Step | Expected | 00434 * |---|--------------------------------|-------------| 00435 * | 1 | Look up the IP address of the test server using `pal_getAddressInfo`. | PAL_SUCCESS | 00436 * | 2 | Create a blocking asynchronous TCP socket with `socketCallback2` as callback. | PAL_SUCCESS | 00437 * | 3 | Set port to a test port in the address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 00438 * | 4 | Connect the socket to the test server using `pal_connect`. | PAL_SUCCESS | 00439 * | 5 | Send a test message (short HTTP request) to the test server using `pal_send`. | PAL_SUCCESS | 00440 * | 6 | Wait for a callback to release the semaphore when the response arrives. | PAL_SUCCESS | 00441 * | 7 | Receive (blocking) the server's response using `pal_recv` and check that the response is HTTP.| PAL_SUCCESS | 00442 * | 8 | Close the socket. | PAL_SUCCESS | 00443 */ 00444 TEST(pal_socket, basicSocketScenario3) 00445 { 00446 palStatus_t result = PAL_SUCCESS; 00447 palSocketAddress_t address = { 0 }; 00448 const char* message = "GET / HTTP/1.0\r\nHost:10.45.48.68:8000\r\n\r\n"; 00449 size_t sent = 0; 00450 char buffer[100] = { 0 }; 00451 size_t read = 0; 00452 s_callbackcounter = 0; 00453 palSocketLength_t addrlen = 0; 00454 int32_t countersAvailable; 00455 00456 result = pal_osSemaphoreCreate(1, &s_semaphoreID); 00457 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00458 result = pal_osSemaphoreWait(s_semaphoreID, 40000, &countersAvailable); 00459 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00460 00461 /*#1*/ 00462 result = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME, &address, &addrlen); 00463 if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result)) 00464 { 00465 PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)"); 00466 return; 00467 } 00468 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00469 00470 00471 00472 #if PAL_NET_ASYNCHRONOUS_SOCKET_API 00473 /*#2*/ 00474 result = pal_asynchronousSocketWithArgument(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, socketCallback2, "socketCallback2Arg", &g_testSockets[0]); 00475 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00476 00477 s_secondCallbackCounter = 0; 00478 result = pal_asynchronousSocketWithArgument(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, socketCallbackErr, "socketCallback2Arg", &g_testSockets[1]); 00479 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00480 00481 TEST_ASSERT_EQUAL_HEX(0, s_secondCallbackCounter); 00482 /*#3*/ 00483 result = pal_setSockAddrPort(&address, PAL_NET_TEST_SERVER_HTTP_PORT); 00484 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00485 00486 /*#4*/ 00487 result = pal_connect(g_testSockets[0], &address, 16); 00488 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00489 00490 TEST_ASSERT_EQUAL_HEX(0, s_secondCallbackCounter); 00491 /*#5*/ 00492 result = pal_send(g_testSockets[0], message, strlen(message), &sent); 00493 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00494 00495 TEST_ASSERT_EQUAL_HEX(0, s_secondCallbackCounter); 00496 // Give a chance for the callback to be called. 00497 /*#6*/ 00498 result=pal_osSemaphoreWait(s_semaphoreID, 40000, &countersAvailable); 00499 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00500 00501 result=pal_osSemaphoreDelete(&s_semaphoreID); 00502 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00503 00504 /*#7*/ 00505 result = pal_recv(g_testSockets[0], buffer, 99, &read); 00506 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00507 TEST_ASSERT(read >= 4); 00508 TEST_ASSERT(buffer[0] == 'H' && buffer[1] == 'T'&& buffer[2] == 'T' && buffer[3] == 'P'); 00509 TEST_ASSERT(s_callbackcounter > 0); 00510 00511 00512 TEST_ASSERT_EQUAL_HEX(0, s_secondCallbackCounter); 00513 /*#8*/ 00514 pal_close(&g_testSockets[0]); 00515 #endif // PAL_NET_ASYNCHRONOUS_SOCKET_API 00516 } 00517 00518 00519 00520 00521 typedef struct palNetTestThreadData{ 00522 palSemaphoreID_t sem1; 00523 palSemaphoreID_t sem2; 00524 uint16_t port; 00525 } palNetTestThreadData_t; 00526 00527 char s_rcv_buffer[20] = {0}; 00528 char s_rcv_buffer2[50] = {0}; 00529 00530 void palNetClientFunc(void const *argument) 00531 { 00532 palStatus_t result = PAL_SUCCESS; 00533 int32_t tmp = 0; 00534 size_t sent = 0; 00535 size_t read = 0; 00536 palNetTestThreadData_t* dualSem = (palNetTestThreadData_t*)argument; 00537 palSocketLength_t addrlen = 16; 00538 //palSocketAddress_t address = { 0 }; 00539 palNetInterfaceInfo_t interfaceInfo; 00540 const char* message = "GET / HTTP/1.0\r\n\r\n"; 00541 00542 /*#C1*/ 00543 result = pal_osSemaphoreWait(dualSem->sem1, 500, &tmp); 00544 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00545 00546 /*#C2*/ 00547 result = pal_getNetInterfaceInfo(PAL_NET_TEST_LOCAL_LOOPBACK_IF_INDEX, &interfaceInfo); 00548 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00549 00550 /*#C3*/ 00551 uint16_t incoming_port = dualSem->port; 00552 PAL_PRINTF("client port = %u", incoming_port); 00553 result = pal_setSockAddrPort(&(interfaceInfo.address), incoming_port); 00554 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00555 00556 /*#C4*/ 00557 result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_testSockets[2]); 00558 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00559 00560 /*#C5*/ 00561 result = pal_connect(g_testSockets[2], &(interfaceInfo.address), addrlen); 00562 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00563 00564 /*#C6*/ 00565 result = pal_send(g_testSockets[2], message, 18, &sent); 00566 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00567 00568 /*#C7*/ 00569 result = pal_recv(g_testSockets[2], s_rcv_buffer, 15, &read); 00570 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00571 00572 /*#C8*/ 00573 pal_close(&g_testSockets[2]); 00574 00575 result = pal_osSemaphoreRelease(dualSem->sem2); 00576 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00577 } 00578 00579 /*! \brief /b ServerSocketScenario tests a TCP client-server scenario using device loopback. 00580 * 00581 * \note The test steps are divided into those in the server main thread (S1..S13) and those in the client thread (C1..C8). 00582 * The sequence below is an approximation of the actual order of execution. 00583 * 00584 ** \test 00585 * | # | Step | Expected | 00586 * |---|--------------------------------|-------------| 00587 * | S1 | Look up the IP address of loopback using `pal_getAddressInfo`. | PAL_SUCCESS | 00588 * | S2 | Create a blocking TCP server socket using `pal_socket`. | PAL_SUCCESS | 00589 * | S3 | Create a blocking TCP socket using `pal_socket`. | PAL_SUCCESS | 00590 * | S4 | Set the port to test port in address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 00591 * | S5 | Bind the server socket to the port and address using `pal_bind`. | PAL_SUCCESS | 00592 * | S6 | Create synchronization sepmaphores and set count to 0. | PAL_SUCCESS | 00593 * | S7 | Create a client thread with `BelowNormal` priority running `palNetClientFunc`. | PAL_SUCCESS | 00594 * | C1 | Client thread blocks on client sepmaphore s1. | PAL_SUCCESS | 00595 * | S8 | Listen to the server port using `pal_listen`. | PAL_SUCCESS | 00596 * | S9 | Release the client sepmahore s1. | PAL_SUCCESS | 00597 * | S10 | Call `accept` (blocking) to accept a new connection (retry in case of failure). | PAL_SUCCESS | 00598 * | C2 | Look up the IP address of the loopback using `pal_getAddressInfo`. | PAL_SUCCESS | 00599 * | C3 | Set the port to test port in the address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 00600 * | C4 | Create a blocking TCP socket using `pal_socket`. | PAL_SUCCESS | 00601 * | C5 | Connect to the server using `pal_connect`. | PAL_SUCCESS | 00602 * | C6 | Send data to server. | PAL_SUCCESS | 00603 * | S11 | Receive data from the client. | PAL_SUCCESS | 00604 * | S12 | Send data to the client. | PAL_SUCCESS | 00605 * | C7 | Receive data from the server. | PAL_SUCCESS | 00606 * | C8 | Client thread cleanup - close the socket and release the semaphore. | PAL_SUCCESS | 00607 * | S13 | Cleanup: close sockets and delete semaphores. | PAL_SUCCESS | 00608 */ 00609 00610 TEST(pal_socket, ServerSocketScenario) 00611 { 00612 palStatus_t result = PAL_SUCCESS; 00613 palSocketAddress_t address2 = { 0 }; 00614 const char* messageOut = "HTTP/1.0 200 OK"; 00615 size_t sent = 0; 00616 size_t read = 0; 00617 palSocketLength_t addrlen = 16; 00618 00619 palSemaphoreID_t semaphoreID = NULLPTR; 00620 palSemaphoreID_t semaphoreID2 = NULLPTR; 00621 palNetTestThreadData_t dualSem = {0}; 00622 palThreadID_t threadID1 = NULLPTR; 00623 int32_t tmp = 0; 00624 palNetInterfaceInfo_t interfaceInfo; 00625 memset(&interfaceInfo,0,sizeof(interfaceInfo)); 00626 00627 00628 /*#S1*/ 00629 result = pal_getNetInterfaceInfo(PAL_NET_TEST_LOCAL_LOOPBACK_IF_INDEX, &interfaceInfo); 00630 if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result)) 00631 { 00632 PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)"); 00633 return; 00634 } 00635 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00636 00637 /*#S2*/ 00638 result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM_SERVER , false, 0, &g_testSockets[0]); 00639 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00640 00641 /*#S3*/ 00642 result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_testSockets[1]); 00643 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00644 00645 /*#S4*/ 00646 uint32_t rand_number = 0; 00647 uint16_t incoming_port; 00648 00649 for (int i=0; i<5; i++) { 00650 pal_osRandomBuffer((uint8_t*)&rand_number, sizeof(rand_number)); 00651 incoming_port = (uint16_t)(35400 + (rand_number % (40000 - 35400))); 00652 PAL_PRINTF("server port = %u", incoming_port); 00653 00654 result = pal_setSockAddrPort(&(interfaceInfo.address), incoming_port); 00655 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00656 00657 /*#S5*/ 00658 result = pal_bind(g_testSockets[0], &(interfaceInfo.address), interfaceInfo.addressSize); 00659 00660 if (PAL_SUCCESS == result) { 00661 PAL_PRINTF("bind succeeded on port %u", incoming_port); 00662 break; 00663 } else { 00664 PAL_PRINTF("bind failed on port %u", incoming_port); 00665 } 00666 } 00667 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00668 00669 /*#S6*/ 00670 00671 // start client thread to connect to the server. 00672 result = pal_osSemaphoreCreate(1 ,&semaphoreID); 00673 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00674 result = pal_osSemaphoreWait(semaphoreID, 1000, &tmp); 00675 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00676 00677 00678 result = pal_osSemaphoreCreate(1 ,&semaphoreID2); 00679 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00680 result = pal_osSemaphoreWait(semaphoreID2, 1000, &tmp); 00681 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00682 00683 dualSem.sem1 = semaphoreID; 00684 dualSem.sem2 = semaphoreID2; 00685 dualSem.port = incoming_port; 00686 00687 /*#S7*/ 00688 result = pal_osThreadCreateWithAlloc(palNetClientFunc, &dualSem , PAL_osPriorityBelowNormal, PAL_TEST_THREAD_STACK_SIZE, NULL, &threadID1); 00689 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00690 00691 /*#S8*/ 00692 result = pal_listen(g_testSockets[0], 10); 00693 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00694 00695 /*#S9*/ 00696 result = pal_osSemaphoreRelease(dualSem.sem1); 00697 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00698 00699 00700 PAL_PRINTF("waiting for connection:\r\n"); 00701 /*#S10*/ 00702 result = pal_accept(g_testSockets[0], &address2, &addrlen, &g_testSockets[1]); 00703 PAL_PRINTF("after accept: %" PRIu32 "\r\n", result); 00704 if (PAL_SUCCESS != result ) 00705 { 00706 result = pal_accept(g_testSockets[0], &address2, &addrlen, &g_testSockets[1]); 00707 PAL_PRINTF("after accept: %" PRIu32 "\r\n",result); 00708 } 00709 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00710 00711 /*#S11*/ 00712 result = pal_recv(g_testSockets[1], s_rcv_buffer2, 49, &read); 00713 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00714 00715 /*#S12*/ 00716 result = pal_send(g_testSockets[1], messageOut, 15, &sent); 00717 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00718 00719 00720 //cleanup 00721 00722 /*#S13*/ 00723 00724 pal_close(&g_testSockets[1]); 00725 pal_close(&g_testSockets[0]); 00726 00727 result = pal_osSemaphoreWait(semaphoreID2, 5000, &tmp); 00728 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00729 pal_osDelay(2000); 00730 pal_osThreadTerminate(&threadID1); 00731 result = pal_osSemaphoreDelete(&semaphoreID); 00732 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00733 TEST_ASSERT_EQUAL_HEX(NULLPTR, semaphoreID); 00734 00735 result = pal_osSemaphoreDelete(&semaphoreID2); 00736 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00737 TEST_ASSERT_EQUAL_HEX(NULLPTR, semaphoreID2); 00738 } 00739 00740 00741 00742 PAL_PRIVATE volatile uint32_t s_callbackCounterNonBlock = 0; 00743 00744 PAL_PRIVATE void nonBlockCallback(void * arg) 00745 { 00746 s_callbackCounterNonBlock++; 00747 } 00748 00749 #define PAL_NET_TEST_HTTP_HEADER_LEN 5 00750 00751 /*! \brief /b nonBlockingAsyncTest checks the asynchronous- nonblocking socket scenario. 00752 ** \test 00753 * | # | Step | Expected | 00754 * |---|--------------------------------|-------------| 00755 * | 1 | Look up the IP address of the test server using `pal_getAddressInfo`. | PAL_SUCCESS | 00756 * | 2 | Create an asynchronous non-blocking TCP socket with `nonBlockCallback` as callback. | PAL_SUCCESS | 00757 * | 3 | Set the port to test port in the address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 00758 * | 4 | Connect the socket. | PAL_SUCCESS or PAL_ERR_SOCKET_IN_PROGRES | 00759 * | 5 | Send a test message to the test server using `pal_send` (repeat until success). | PAL_SUCCESS or PAL_ERR_SOCKET_IN_PROGRES | 00760 * | 6 | Wait for the callback and receive server response using `pal_recv` (repeat until success). | PAL_SUCCESS or PAL_ERR_SOCKET_WOULD_BLOCK| 00761 * | 7 | Close the socket. | PAL_SUCCESS | 00762 */ 00763 TEST(pal_socket, nonBlockingAsyncTest) 00764 { 00765 palStatus_t result = PAL_SUCCESS; 00766 palSocketAddress_t address = { 0 }; 00767 const char* message = "GET / HTTP/1.0\r\nHost:10.45.48.68:8000\r\n\r\n"; 00768 size_t sent = 0; 00769 char buffer[100] = { 0 }; 00770 size_t read = 0; 00771 s_callbackcounter = 0; 00772 palSocketLength_t addrlen = 0; 00773 int32_t waitIterations = 0; 00774 00775 /*#1*/ 00776 result = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME, &address, &addrlen); 00777 if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result)) 00778 { 00779 PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)"); 00780 return; 00781 } 00782 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00783 00784 #if PAL_NET_ASYNCHRONOUS_SOCKET_API 00785 /*#2*/ 00786 result = pal_asynchronousSocketWithArgument(PAL_AF_INET, PAL_SOCK_STREAM, true, 0, nonBlockCallback, "non-blockSocketCallbackArg", &g_testSockets[0]); 00787 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00788 00789 /*#3*/ 00790 result = pal_setSockAddrPort(&address, PAL_NET_TEST_SERVER_HTTP_PORT); 00791 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00792 00793 /*#4*/ 00794 result = pal_connect(g_testSockets[0], &address, 16); 00795 if (PAL_ERR_SOCKET_IN_PROGRES == result) 00796 { 00797 result = pal_connect(g_testSockets[0], &address, 16); 00798 if ((result != PAL_SUCCESS) && (result != PAL_ERR_SOCKET_ALREADY_CONNECTED ) && (result != PAL_ERR_SOCKET_IN_PROGRES ) && (result != PAL_ERR_SOCKET_WOULD_BLOCK )) // check expected result codes.(connection should either be in progress or connected already) 00799 { 00800 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00801 } 00802 pal_osDelay(400); 00803 } 00804 else 00805 { 00806 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00807 } 00808 s_callbackCounterNonBlock = 0; 00809 00810 /*#5*/ 00811 result = pal_send(g_testSockets[0], message, strlen(message), &sent); 00812 00813 while (PAL_ERR_SOCKET_IN_PROGRES == result) 00814 { 00815 pal_osDelay(100); 00816 result = pal_send(g_testSockets[0], message, strlen(message), &sent); 00817 } 00818 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00819 00820 /*#6*/ 00821 result = pal_recv(g_testSockets[0], buffer, PAL_NET_TEST_HTTP_HEADER_LEN, &read); // may block 00822 while ((PAL_ERR_SOCKET_WOULD_BLOCK == result) && (10 > waitIterations )) 00823 { 00824 s_callbackCounterNonBlock = 0; 00825 while (s_callbackCounterNonBlock == 0) 00826 { 00827 waitIterations++; 00828 pal_osDelay(100); 00829 } 00830 result = pal_recv(g_testSockets[0], buffer, PAL_NET_TEST_HTTP_HEADER_LEN, &read); // shouldnt block 00831 } 00832 00833 /*#7*/ 00834 pal_close(&g_testSockets[0]); 00835 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00836 TEST_ASSERT(read >= 4); 00837 TEST_ASSERT(buffer[0] == 'H' && buffer[1] == 'T'&& buffer[2] == 'T' && buffer[3] == 'P'); 00838 TEST_ASSERT(s_callbackCounterNonBlock > 0); 00839 00840 #endif // PAL_NET_ASYNCHRONOUS_SOCKET_API 00841 } 00842 00843 /*! \brief /b tProvUDPTest tests UDP socket send/receive and checks that we get the correct error for receive timeout. 00844 ** \test 00845 * | # | Step | Expected | 00846 * |---|--------------------------------|-------------| 00847 * | 1 | Create a blocking UDP socket using `pal_socket`. | PAL_SUCCESS | 00848 * | 2 | Look up the IP address of the test server using `pal_getAddressInfo`. | PAL_SUCCESS | 00849 * | 3 | Set the port to test port in the address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 00850 * | 4 | Set socket timeouts using `pal_setSocketOptions`. | PAL_SUCCESS | 00851 * | 5 | Send a test message (short HTTP request) to test the server using `pal_send`. | PAL_SUCCESS | 00852 * | 6 | Receive the (blocking) server response using `pal_recv`. | PAL_SUCCESS | 00853 * | 7 | Receive the (blocking) server response again using `pal_recv` and fail. | PAL_ERR_SOCKET_WOULD_BLOCK | 00854 * | 8 | Close the socket. | PAL_SUCCESS | 00855 */ 00856 TEST(pal_socket, tProvUDPTest) 00857 { 00858 palStatus_t result = PAL_SUCCESS; 00859 palSocketAddress_t address = { 0,{0} }; 00860 uint8_t buffer[100] = { 0 }; 00861 uint8_t buffer_dns[33] = { 0x8e, 0xde, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x61, 0x72, 0x73, 0x74, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x63, 0x61, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 }; 00862 size_t sent = 0; 00863 size_t read = 0; 00864 palSocketLength_t addrlen = 16; 00865 int timeout = PAL_MILLI_PER_SECOND; 00866 00867 /*#1*/ 00868 result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM , false, 0, &g_testSockets[0]); 00869 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00870 00871 /*#2*/ 00872 result = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME_UDP, &address, &addrlen); 00873 if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result)) 00874 { 00875 PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)"); 00876 goto end; 00877 } 00878 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00879 00880 /*#3*/ 00881 result = pal_setSockAddrPort(&address, PAL_NET_TEST_SERVER_UDP_PORT); 00882 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00883 00884 /*#4*/ 00885 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_SNDTIMEO , &timeout, sizeof(timeout)); 00886 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00887 00888 timeout = 1000; 00889 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO , &timeout, sizeof(timeout)); 00890 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00891 00892 /*#5*/ 00893 result = pal_sendTo(g_testSockets[0], buffer_dns, sizeof(buffer_dns), &address, addrlen, &sent); 00894 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00895 TEST_ASSERT_EQUAL_HEX(sent, sizeof(buffer_dns)); 00896 00897 /*#6*/ 00898 result = pal_receiveFrom(g_testSockets[0], buffer, 16, NULL, NULL, &read); 00899 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00900 TEST_ASSERT_EQUAL(read, 16); 00901 00902 /*#7*/ 00903 result = pal_receiveFrom(g_testSockets[0], buffer, 100, NULL, NULL, &read); // should get timeout 00904 TEST_ASSERT_EQUAL_HEX(result, PAL_ERR_SOCKET_WOULD_BLOCK ); 00905 00906 end: 00907 /*#8*/ 00908 pal_close(&g_testSockets[0]); 00909 } 00910 00911 00912 PAL_PRIVATE void fillUDPTestBuffer(pal_udp_test_data_t *data, uint8_t* buffer) 00913 { 00914 memset(buffer, 0, data->bufferSize); 00915 data->chunkSize = (data->messageSize - data->totalSize > data->bufferSize) ? data->bufferSize : (data->messageSize - data->totalSize); 00916 memset(buffer, ++(data->currentValue), data->chunkSize); 00917 data->totalSize += data->chunkSize; 00918 } 00919 00920 // UDP test sender thread function. 00921 PAL_PRIVATE void socketUDPBufferedTestSender(const void *arg) 00922 { 00923 palStatus_t result = PAL_SUCCESS; 00924 pal_udp_test_data_t *data = (pal_udp_test_data_t*)arg; // cast from const to non-const 00925 size_t sent = 0, totalSent = 0; 00926 00927 g_testSendBuffer = (uint8_t*)malloc(sizeof(uint8_t) * data->bufferSize); 00928 TEST_ASSERT_NOT_EQUAL(NULLPTR, g_testSendBuffer); 00929 00930 data->totalSize = 0; 00931 data->chunkSize = 0; 00932 data->currentValue = data->startValue; 00933 while (totalSent != data->messageSize) 00934 { 00935 fillUDPTestBuffer(data, g_testSendBuffer); 00936 result = pal_sendTo(g_testSockets[0], g_testSendBuffer, data->chunkSize, &(data->interfaceInfo.address), data->interfaceInfo.addressSize, &sent); 00937 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00938 totalSent += sent; 00939 pal_osDelay(5); // allow some time for the RX bits to be set 00940 }; 00941 00942 free(g_testSendBuffer); 00943 g_testSendBuffer = NULLPTR; 00944 } 00945 00946 /*! \brief Test UDP socket read in chunks 00947 * 00948 * \note The test generates data and calculates its hash, then this data is re-generated from a dedicated thread and 00949 * received on the current thread which calculates the received data hash and compares it to the original hash 00950 * 00951 * @param[in] bufSize - the read buffer size 00952 * 00953 ** \test 00954 * | # | Step | Expected | 00955 * |---|--------------------------------|-------------| 00956 * | 1 | Initialize the MD context. | PAL_SUCCESS | 00957 * | 2 | Allocate buffer. | PAL_SUCCESS | 00958 * | 3 | Generate data incrementally and update the MD context. | PAL_SUCCESS | 00959 * | 4 | Get the hash output size and validate it. | PAL_SUCCESS | 00960 * | 5 | Get the calculated hash. | PAL_SUCCESS | 00961 * | 6 | Free the MD context resources. | PAL_SUCCESS | 00962 * | 7 | Get the interface address. | PAL_SUCCESS | 00963 * | 8 | Create a (blocking) UDP socket. | PAL_SUCCESS | 00964 * | 9 | Set the socket port and set send/receive timeouts. | PAL_SUCCESS | 00965 * | 10 | Bind the socket. | PAL_SUCCESS | 00966 * | 11 | Initialize the MD context. | PAL_SUCCESS | 00967 * | 12 | Launch the data sender thread. | PAL_SUCCESS | 00968 * | 13 | Read data from the socket until there's no more data or all data has been received. | PAL_SUCCESS | 00969 * | 14 | Update the MD context. | PAL_SUCCESS | 00970 * | 15 | Terminate the sending thread. | PAL_SUCCESS | 00971 * | 16 | Close the socket. | PAL_SUCCESS | 00972 * | 17 | Get the hash output size and validate it. | PAL_SUCCESS | 00973 * | 18 | Get the calculated hash and compare it. | PAL_SUCCESS | 00974 * | 19 | Free the MD context resources. | PAL_SUCCESS | 00975 * | 20 | Free allocated buffer. | PAL_SUCCESS | 00976 */ 00977 PAL_PRIVATE void socketUDPBuffered(size_t bufSize) 00978 { 00979 palStatus_t result = PAL_SUCCESS; 00980 pal_udp_test_data_t data = { PAL_NET_TEST_BUFFERED_UDP_MESSAGE_SIZE, bufSize, 0 }; 00981 uint8_t expectedHash[PAL_SHA256_SIZE] = { 0 }, actualHash[PAL_SHA256_SIZE] = { 0 }; 00982 size_t read = 0, totalRead = 0, hashlen = 0; 00983 int timeout = PAL_MILLI_PER_SECOND; 00984 palMDHandle_t handle = NULLPTR; 00985 palThreadID_t thread = NULLPTR; 00986 00987 /*#1*/ 00988 result = pal_mdInit(&handle, PAL_SHA256); 00989 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00990 TEST_ASSERT_NOT_EQUAL(NULLPTR, handle); 00991 00992 /*#2*/ 00993 g_testRecvBuffer = (uint8_t*)malloc(sizeof(uint8_t) * bufSize); 00994 TEST_ASSERT_NOT_EQUAL(NULLPTR, g_testRecvBuffer); 00995 00996 /*#3*/ 00997 data.totalSize = data.chunkSize = 0; 00998 data.currentValue = data.startValue; 00999 while (data.totalSize != data.messageSize) 01000 { 01001 fillUDPTestBuffer(&data, g_testRecvBuffer); 01002 result = pal_mdUpdate(handle, g_testRecvBuffer, data.chunkSize); 01003 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01004 }; 01005 01006 /*#4*/ 01007 result = pal_mdGetOutputSize(handle, &hashlen); 01008 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01009 TEST_ASSERT_EQUAL_HEX(PAL_SHA256_SIZE, hashlen); 01010 01011 /*#5*/ 01012 result = pal_mdFinal(handle, expectedHash); 01013 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01014 01015 /*#6*/ 01016 result = pal_mdFree(&handle); 01017 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01018 01019 /*#7*/ 01020 memset(&(data.interfaceInfo), 0, sizeof(data.interfaceInfo)); 01021 result = pal_getNetInterfaceInfo(0, &(data.interfaceInfo)); 01022 if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result)) 01023 { 01024 PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)"); 01025 goto end; 01026 } 01027 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01028 01029 /*#8*/ 01030 result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM , false, 0, &g_testSockets[0]); 01031 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01032 01033 /*#9*/ 01034 result = pal_setSockAddrPort(&(data.interfaceInfo.address), PAL_NET_TEST_BUFFERED_UDP_PORT); 01035 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01036 01037 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO , &timeout, sizeof(timeout)); 01038 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01039 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_SNDTIMEO , &timeout, sizeof(timeout)); 01040 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01041 01042 /*#10*/ 01043 result = pal_bind(g_testSockets[0], &(data.interfaceInfo.address), data.interfaceInfo.addressSize); 01044 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01045 01046 /*#11*/ 01047 handle = NULLPTR; 01048 result = pal_mdInit(&handle, PAL_SHA256); 01049 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01050 TEST_ASSERT_NOT_EQUAL(NULLPTR, handle); 01051 01052 /*#12*/ 01053 result = pal_osThreadCreateWithAlloc(socketUDPBufferedTestSender, &data, PAL_osPriorityNormal, PAL_TEST_THREAD_STACK_SIZE, NULL, &thread); 01054 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01055 TEST_ASSERT_NOT_EQUAL(NULLPTR, thread); 01056 01057 /*#13*/ 01058 do 01059 { 01060 read = 0; 01061 memset(g_testRecvBuffer, 0, data.bufferSize); 01062 result = pal_receiveFrom(g_testSockets[0], g_testRecvBuffer, data.bufferSize, &(data.interfaceInfo.address), &(data.interfaceInfo.addressSize), &read); 01063 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01064 /*#14*/ 01065 result = pal_mdUpdate(handle, g_testRecvBuffer, read); 01066 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01067 totalRead += read; 01068 } while (read > 0 && totalRead < data.messageSize); 01069 01070 /*#15*/ 01071 result = pal_osThreadTerminate(&thread); 01072 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01073 01074 /*#16*/ 01075 result = pal_close(&g_testSockets[0]); 01076 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01077 01078 /*#17*/ 01079 hashlen = 0; 01080 result = pal_mdGetOutputSize(handle, &hashlen); 01081 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01082 TEST_ASSERT_EQUAL_HEX(PAL_SHA256_SIZE, hashlen); 01083 01084 /*#18*/ 01085 result = pal_mdFinal(handle, actualHash); 01086 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01087 TEST_ASSERT_EQUAL_MEMORY(expectedHash, actualHash, PAL_SHA256_SIZE); 01088 01089 /*#19*/ 01090 result = pal_mdFree(&handle); 01091 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01092 01093 /*#20*/ 01094 end: 01095 free(g_testRecvBuffer); 01096 g_testRecvBuffer = NULLPTR; 01097 } 01098 01099 /*! \brief Test function UDP socket read in small chunks 01100 * 01101 ** \test 01102 */ 01103 TEST(pal_socket, socketUDPBufferedSmall) 01104 { 01105 socketUDPBuffered(PAL_NET_TEST_BUFFERED_UDP_BUF_SIZE_SMALL); 01106 } 01107 01108 /*! \brief Test function UDP socket read in large chunks 01109 * 01110 ** \test 01111 */ 01112 TEST(pal_socket, socketUDPBufferedLarge) 01113 { 01114 socketUDPBuffered(PAL_NET_TEST_BUFFERED_UDP_BUF_SIZE_LARGE); 01115 } 01116 01117 #ifdef __LINUX__ // Linux CI tests for socketTCPBufferedSmall & socketTCPBufferedLarge must use an ipv4 address in order to connect to the external host 01118 #if PAL_SUPPORT_IP_V4 01119 PAL_PRIVATE palStatus_t getAddressInfoIPv4(char const *url, palSocketAddress_t *address, palSocketLength_t* addressLength) 01120 { 01121 struct addrinfo *info = NULLPTR; 01122 struct addrinfo hints = { 0 }; 01123 struct sockaddr_in *sockAddress = NULLPTR; 01124 palIpV4Addr_t ipV4Address = { 0 }; 01125 int ret; 01126 palStatus_t result; 01127 01128 hints.ai_family = AF_INET; 01129 ret = getaddrinfo(url, NULL, &hints, &info); 01130 TEST_ASSERT_EQUAL(0, ret); 01131 TEST_ASSERT_NOT_EQUAL(NULLPTR, info); 01132 TEST_ASSERT_EQUAL(AF_INET, info->ai_family); 01133 01134 sockAddress = (struct sockaddr_in*)info->ai_addr; 01135 memcpy(ipV4Address, &(sockAddress->sin_addr), PAL_IPV4_ADDRESS_SIZE); 01136 freeaddrinfo(info); 01137 01138 result = pal_setSockAddrIPV4Addr(address, ipV4Address); 01139 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01140 *addressLength = sizeof(struct sockaddr_in); 01141 return result; 01142 } 01143 #endif 01144 #endif 01145 01146 /*! \brief Test TCP socket read in chunks 01147 * 01148 * \note The test attempts to perform an HTTP get request to a google (jquery) CDN, read the file in chunks (ignoring HTTP headers) and compare its hash to a pre-known hash using SHA256. 01149 * 01150 * @param[in] bufSize - the read buffer size 01151 * 01152 ** \test 01153 * | # | Step | Expected | 01154 * |---|--------------------------------|-------------| 01155 * | 1 | Create a (blocking) TCP socket. | PAL_SUCCESS | 01156 * | 2 | Look up the IP address of the CDN server. | PAL_SUCCESS | 01157 * | 3 | Set the port to the CDN server's HTTP port and set send/receive timeouts. | PAL_SUCCESS | 01158 * | 4 | Connect the socket to the CDN server. | PAL_SUCCESS | 01159 * | 5 | Send an HTTP get request to the CDN server. | PAL_SUCCESS | 01160 * | 6 | Initialize the MD context. | PAL_SUCCESS | 01161 * | 7 | Allocate HTTP response buffer. | PAL_SUCCESS | 01162 * | 8 | Read the server's response until there's no more data to read. | PAL_SUCCESS | 01163 * | 9 | If we're done dealing with the HTTP headers then update the MD context. | PAL_SUCCESS | 01164 * | 10 | Locate the end of the HTTP headers in the server's response (HTTP headers end with a double CRLF). | PAL_SUCCESS | 01165 * | 11 | Update the MD context. | PAL_SUCCESS | 01166 * | 12 | Close the socket. | PAL_SUCCESS | 01167 * | 13 | Get the hash output size and validate it. | PAL_SUCCESS | 01168 * | 14 | Get the calculated hash and compare it to the pre-known hash. | PAL_SUCCESS | 01169 * | 15 | Free the MD context resources. | PAL_SUCCESS | 01170 * | 16 | Free HTTP response buffer. | PAL_SUCCESS | 01171 */ 01172 PAL_PRIVATE void socketTCPBuffered(size_t bufSize) 01173 { 01174 palStatus_t result = PAL_SUCCESS; 01175 palSocketAddress_t address = { 0 }; 01176 palSocketLength_t addrlen = 0; 01177 int timeout = 5000; 01178 uint8_t next = '\r', state = 0; 01179 size_t read = 0, sent = 0, hashlen = 0; 01180 bool body = false; 01181 palMDHandle_t handle = NULLPTR; 01182 uint8_t actualHash[PAL_SHA256_SIZE] = { 0 }; 01183 const uint8_t expectedHash[] = // pre-calculated jquery.js 3.2.1 SHA256 01184 { 01185 0x0d, 0x90, 0x27, 0x28, 0x9f, 0xfa, 0x5d, 0x9f, 0x6c, 0x8b, 0x4e, 0x07, 0x82, 0xbb, 0x31, 0xbb, 01186 0xff, 0x2c, 0xef, 0x5e, 0xe3, 0x70, 0x8c, 0xcb, 0xcb, 0x7a, 0x22, 0xdf, 0x91, 0x28, 0xbb, 0x21 01187 }; 01188 01189 01190 01191 /*#2*/ 01192 result = test_getAddressInfo(PAL_NET_TEST_GOOGLE_CDN_HOST, &address, &addrlen); 01193 if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result)) 01194 { 01195 PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)"); 01196 return; 01197 } 01198 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01199 01200 /*#1*/ 01201 result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_testSockets[0]); 01202 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01203 01204 /*#3*/ 01205 result = pal_setSockAddrPort(&address, PAL_NET_TEST_GOOGLE_CDN_HOST_PORT); 01206 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01207 01208 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_SNDTIMEO , &timeout, sizeof(timeout)); 01209 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01210 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO , &timeout, sizeof(timeout)); 01211 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01212 01213 /*#4*/ 01214 result = pal_connect(g_testSockets[0], &address, addrlen); 01215 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01216 01217 /*#5*/ 01218 result = pal_send(g_testSockets[0], PAL_NET_TEST_GOOGLE_CDN_REQUEST, sizeof(PAL_NET_TEST_GOOGLE_CDN_REQUEST) - 1, &sent); 01219 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01220 01221 /*#6*/ 01222 result = pal_mdInit(&handle, PAL_SHA256); 01223 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01224 TEST_ASSERT_NOT_EQUAL(NULLPTR, handle); 01225 01226 /*#7*/ 01227 g_testRecvBuffer = (uint8_t*)malloc(sizeof(uint8_t) * bufSize + 1); 01228 TEST_ASSERT_NOT_EQUAL(NULLPTR, g_testRecvBuffer); 01229 01230 /*#8*/ 01231 do 01232 { 01233 read = 0; 01234 memset(g_testRecvBuffer, 0, bufSize + 1); 01235 result = pal_recv(g_testSockets[0], g_testRecvBuffer, bufSize, &read); 01236 TEST_ASSERT_TRUE((PAL_SUCCESS == result && read > 0) || (PAL_ERR_SOCKET_CONNECTION_CLOSED == result && read == 0)); 01237 01238 /*#9*/ 01239 if (body) 01240 { 01241 result = pal_mdUpdate(handle, g_testRecvBuffer, read); 01242 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01243 continue; 01244 } 01245 01246 /*#10*/ 01247 for (size_t i = 0; i < bufSize; i++) // dealing with the HTTP headers - headers end on a double CRLF 01248 { 01249 if (g_testRecvBuffer[i] == next) 01250 { 01251 next = (next == '\r') ? '\n' : '\r'; 01252 state = state | (state + 1); 01253 if (state == 0xf) 01254 { 01255 /*#11*/ 01256 body = true; 01257 result = pal_mdUpdate(handle, (g_testRecvBuffer + i + 1), strlen(((char*)g_testRecvBuffer) + i + 1)); 01258 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01259 break; 01260 } 01261 } 01262 else if (state != 0) 01263 { 01264 next = '\r'; 01265 state = 0; 01266 } 01267 } 01268 } while (read > 0); 01269 01270 /*#12*/ 01271 result = pal_close(&g_testSockets[0]); 01272 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01273 01274 /*#13*/ 01275 result = pal_mdGetOutputSize(handle, &hashlen); 01276 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01277 TEST_ASSERT_EQUAL_HEX(PAL_SHA256_SIZE, hashlen); 01278 01279 /*#14*/ 01280 result = pal_mdFinal(handle, actualHash); 01281 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01282 TEST_ASSERT_EQUAL_MEMORY(expectedHash, actualHash, PAL_SHA256_SIZE); 01283 01284 /*#15*/ 01285 result = pal_mdFree(&handle); 01286 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01287 01288 /*#16*/ 01289 free(g_testRecvBuffer); 01290 g_testRecvBuffer = NULLPTR; 01291 01292 } 01293 01294 /*! \brief Test function TCP socket read in small chunks 01295 * 01296 ** \test 01297 */ 01298 TEST(pal_socket, socketTCPBufferedSmall) 01299 { 01300 socketTCPBuffered(PAL_NET_TEST_BUFFERED_TCP_BUF_SIZE_SMALL); 01301 } 01302 01303 /*! \brief Test function TCP socket read in large chunks 01304 * 01305 ** \test 01306 */ 01307 TEST(pal_socket, socketTCPBufferedLarge) 01308 { 01309 socketTCPBuffered(PAL_NET_TEST_BUFFERED_TCP_BUF_SIZE_LARGE); 01310 } 01311 01312 // flag marking if the pal_getAddressInfoAsync callback has been invoked 01313 PAL_PRIVATE bool g_getAddressInfoAsyncCallbackInvoked = false; 01314 01315 // callback invoked from the call to pal_getAddressInfoAsync 01316 PAL_PRIVATE void getAddressInfoAsyncCallback(const char* url, palSocketAddress_t* address, palSocketLength_t* addressLength, palStatus_t status, void* arg) 01317 { 01318 palStatus_t* statusArg = (palStatus_t*)arg; 01319 *statusArg = status; 01320 g_getAddressInfoAsyncCallbackInvoked = true; 01321 } 01322 01323 /*! \brief Test get address info asynchronously 01324 ** \test 01325 * | # | Step | Expected | 01326 * |---|-------------------------------------------------------------------------------------------------------|-------------| 01327 * | 1 | Invoke a synchronous get address info so we'll have something to compare to the asynchronous results. | PAL_SUCCESS | 01328 * | 2 | Invoke an asynchronous get address info. | PAL_SUCCESS | 01329 * | 3 | Wait until the asynchronous get address info callback is called or max wait time has ended. | PAL_SUCCESS | 01330 * | 4 | Compare the synchronous results to the asynchronous results. | PAL_SUCCESS | 01331 */ 01332 TEST(pal_socket, getAddressInfoAsync) 01333 { 01334 int counter = 0; 01335 palSocketAddress_t addressSync = { 0 }, addressAsync = { 0 }; 01336 palSocketLength_t addrlenSync = 0, addrlenAsync = 0; 01337 palStatus_t status, statusCallback; 01338 01339 /*#1*/ 01340 status = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME, &addressSync, &addrlenSync); 01341 if ((PAL_ERR_SOCKET_DNS_ERROR == status) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == status)) 01342 { 01343 PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)"); 01344 return; 01345 } 01346 TEST_ASSERT_TRUE_MESSAGE((PAL_SUCCESS == status), "synchronous call to pal_getAddressInfo failed"); 01347 01348 /*#2*/ 01349 statusCallback = PAL_ERR_SOCKET_ERROR_BASE ; 01350 status = pal_getAddressInfoAsync(PAL_NET_TEST_SERVER_NAME, &addressAsync, &addrlenAsync, getAddressInfoAsyncCallback, &statusCallback); 01351 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 01352 01353 /*#3*/ 01354 while ((!g_getAddressInfoAsyncCallbackInvoked) && counter < 20) // wait until callback is invoked or max time of ~5 seconds 01355 { 01356 counter++; 01357 pal_osDelay(250); 01358 } 01359 TEST_ASSERT_TRUE_MESSAGE(g_getAddressInfoAsyncCallbackInvoked, "getAddressInfoAsyncCallback was not invoked"); 01360 g_getAddressInfoAsyncCallbackInvoked = false; 01361 01362 /*#4*/ 01363 TEST_ASSERT_EQUAL_HEX(status, statusCallback); 01364 TEST_ASSERT_EQUAL_HEX(addrlenSync, addrlenAsync); 01365 TEST_ASSERT_EQUAL_HEX(addressSync.addressType, addressAsync.addressType); 01366 TEST_ASSERT_EQUAL_MEMORY(addressSync.addressData, addressAsync.addressData, PAL_NET_MAX_ADDR_SIZE); 01367 01368 } 01369 01370 /*! \brief Test pal socket APIs input parameter validations 01371 ** \test 01372 */ 01373 TEST(pal_socket, socketApiInputParamValidation) 01374 { 01375 #ifdef DEBUG 01376 palStatus_t status; 01377 palSocketAddress_t addr; 01378 addr.addressType = PAL_AF_UNSPEC; 01379 uint16_t port = 0; 01380 01381 status = pal_registerNetworkInterface(NULL, NULL); 01382 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01383 status = pal_setSockAddrPort(NULL, 0); 01384 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01385 status = pal_setSockAddrPort(&addr, 0); 01386 TEST_ASSERT_EQUAL_HEX(PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY , status); 01387 #if PAL_SUPPORT_IP_V4 01388 status = pal_setSockAddrIPV4Addr(NULL, NULL); 01389 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01390 status = pal_getSockAddrIPV4Addr(NULL, NULL); 01391 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01392 status = pal_getSockAddrIPV4Addr(&addr, NULL); 01393 TEST_ASSERT_EQUAL_HEX(PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY , status); 01394 #endif 01395 #if PAL_SUPPORT_IP_V6 01396 status = pal_setSockAddrIPV6Addr(NULL, NULL); 01397 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01398 status = pal_getSockAddrIPV6Addr(NULL, NULL); 01399 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01400 status = pal_getSockAddrIPV6Addr(&addr, NULL); 01401 TEST_ASSERT_EQUAL_HEX(PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY , status); 01402 #endif 01403 status = pal_getSockAddrPort(NULL, NULL); 01404 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01405 status = pal_getSockAddrPort(&addr, &port); 01406 TEST_ASSERT_EQUAL_HEX(PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY , status); 01407 status = pal_setSocketOptions(NULL, 0, NULL, 0); 01408 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01409 status = pal_isNonBlocking(NULL, NULL); 01410 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01411 status = pal_bind(NULL, NULL, 0); 01412 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01413 status = pal_receiveFrom(NULL, NULL, 0, NULL, NULL, NULL); 01414 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01415 status = pal_sendTo(NULL, NULL, 0, NULL, 0, NULL); 01416 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01417 status = pal_close(NULL); 01418 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01419 status = pal_getNumberOfNetInterfaces(NULL); 01420 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01421 status = pal_getNetInterfaceInfo(0, NULL); 01422 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01423 #if PAL_NET_TCP_AND_TLS_SUPPORT 01424 status = pal_accept(NULL, NULL, NULL, NULL); 01425 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01426 status = pal_connect(NULL, NULL, 0); 01427 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01428 status = pal_recv(NULL, NULL, 0, NULL); 01429 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01430 status = pal_send(NULL, NULL, 0, NULL); 01431 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01432 #endif // PAL_NET_TCP_AND_TLS_SUPPORT 01433 #if PAL_NET_ASYNCHRONOUS_SOCKET_API 01434 status = pal_asynchronousSocketWithArgument(PAL_AF_UNSPEC, PAL_SOCK_DGRAM , false, 0, NULL, NULL, NULL); 01435 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01436 #endif // PAL_NET_ASYNCHRONOUS_SOCKET_API 01437 #if PAL_NET_DNS_SUPPORT 01438 status = pal_getAddressInfo(NULL, NULL, NULL); 01439 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01440 status = pal_getAddressInfoAsync(NULL, NULL, NULL, NULL, NULL); 01441 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 01442 #endif // PAL_NET_DNS_SUPPORT 01443 #endif //DEBUG 01444 } 01445 01446 PAL_PRIVATE void keepAliveFunc(bool keepalive) 01447 { 01448 palStatus_t result = PAL_SUCCESS; 01449 palSocketAddress_t address = { 0 }; 01450 char buffer[100] = { 0 }; 01451 size_t read = 0; 01452 palSocketLength_t addrlen = 0; 01453 int timeout = PAL_MILLI_PER_SECOND; 01454 int KeepAliveOn = 0, KeepAliveIntvl = 0, KeepAliveIdle = 0; 01455 int keepaliveNumber=0; 01456 01457 if (keepalive) 01458 { 01459 KeepAliveOn=1; 01460 KeepAliveIntvl=1; 01461 KeepAliveIdle =1; 01462 } 01463 /*#1*/ 01464 result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_testSockets[0]); 01465 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 01466 01467 /*#2*/ 01468 result = pal_getAddressInfo(PAL_TEST_KEEPALIVE_SERVER_ADDRESS, &address, &addrlen); 01469 if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result)) 01470 { 01471 PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)"); 01472 goto end; 01473 } 01474 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 01475 01476 /*#3*/ 01477 result = pal_setSockAddrPort(&address, PAL_TEST_SERVER_KEEPALIVE_PORT); 01478 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 01479 01480 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_SNDTIMEO , &timeout, sizeof(timeout)); 01481 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01482 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO , &timeout, sizeof(timeout)); 01483 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01484 01485 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_KEEPALIVE , &KeepAliveOn, sizeof(KeepAliveOn)); 01486 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01487 if (keepalive) { 01488 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_KEEPIDLE , &KeepAliveIdle, sizeof(KeepAliveIdle)); 01489 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01490 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_KEEPINTVL , &KeepAliveIntvl, sizeof(KeepAliveIntvl)); 01491 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01492 } 01493 01494 /*#4*/ 01495 result = pal_connect(g_testSockets[0], &address, 16); 01496 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 01497 01498 /*#6*/ 01499 while (result != PAL_ERR_SOCKET_CONNECTION_CLOSED ) 01500 { 01501 result = pal_recv(g_testSockets[0], buffer, sizeof(buffer)-1 , &read); 01502 if (result != PAL_ERR_SOCKET_CONNECTION_CLOSED ) 01503 { 01504 if((read != 0) && (buffer[0]!=0)) 01505 { 01506 keepaliveNumber=atoi(buffer); 01507 if (keepalive){ 01508 TEST_ASSERT_TRUE(keepaliveNumber > PAL_TEST_KEEPALIVE_NUM_OF_ACK); 01509 } 01510 else{ 01511 TEST_ASSERT_TRUE(keepaliveNumber < PAL_TEST_KEEPALIVE_NUM_OF_ACK); 01512 } 01513 break; 01514 } 01515 } 01516 01517 } 01518 end: 01519 result = pal_close(&g_testSockets[0]); 01520 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 01521 } 01522 01523 /*! \brief Test keepAlive On/Off 01524 ** \test 01525 * | # | Step | Expected | 01526 * |---|--------------------------------|-------------| 01527 * | 1 | Create a blocking TCP socket using `pal_socket`. | PAL_SUCCESS | 01528 * | 2 | Look up the IP address of the test server using `pal_getAddressInfo`. | PAL_SUCCESS | 01529 * | 3 | Set the port to a test port in the address structure using `pal_setSockAddrPort` and set timeout. | PAL_SUCCESS | 01530 * | 4 | Set keepalive socket options : if keepalive is on set keepalibe idel and intvl . | PAL_SUCCESS | 01531 * | 5 | Connect the socket to the test server using `pal_connect`. | PAL_SUCCESS | 01532 * | 6 | Receive (blocking) the server's response using `pal_recv` and check it keepalive packates sent. | PAL_SUCCESS | 01533 * | 7 | Close the socket. | PAL_SUCCESS | 01534 */ 01535 01536 TEST(pal_socket, keepaliveOn) 01537 { 01538 keepAliveFunc(true); 01539 } 01540 01541 TEST(pal_socket, keepaliveOff) 01542 { 01543 keepAliveFunc(false); 01544 } 01545 01546
Generated on Tue Jul 12 2022 19:12:15 by 1.7.2