Simple interface for Mbed Cloud Client

Dependents:  

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