Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pal_socket_test.c Source File

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