Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

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