Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers download_test.cpp Source File

download_test.cpp

00001 /*
00002  * mbed Microcontroller Library
00003  * Copyright (c) 2006-2018 ARM Limited
00004  *
00005  * SPDX-License-Identifier: Apache-2.0
00006  *
00007  * Licensed under the Apache License, Version 2.0 (the "License");
00008  * you may not use this file except in compliance with the License.
00009  * You may obtain a copy of the License at
00010  *
00011  *     http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  * Unless required by applicable law or agreed to in writing, software
00014  * distributed under the License is distributed on an "AS IS" BASIS,
00015  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  * See the License for the specific language governing permissions and
00017  * limitations under the License.
00018  */
00019 
00020 /*
00021  * Based on mbed-stress-test by Marcus Chang @ Arm Mbed - http://github.com/ARMmbed/mbed-stress-test
00022 */
00023 
00024 #include "mbed.h"
00025 #include "unity/unity.h"
00026 #include "greentea-client/test_env.h"
00027 #include <string>
00028 
00029 #define MAX_THREADS 5
00030 
00031 #define MAX_RETRIES 3
00032 
00033 #ifdef MBED_CONF_DOWNLOAD_TEST_URL_HOST
00034   const char dl_host[] = MBED_CONF_DOWNLOAD_TEST_URL_HOST;
00035 #else
00036   const char dl_host[] = "armmbed.github.io";
00037 #endif
00038 #ifdef MBED_CONF_DOWNLOAD_TEST_URL_PATH
00039   const char dl_path[] = MBED_CONF_DOWNLOAD_TEST_URL_PATH;
00040 #else
00041   const char dl_path[] = "/mbed-test-files/alice.txt";
00042 #endif
00043 
00044 const char req_template[] = "GET %s  HTTP/1.1\nHost: %s\n\n";
00045 
00046 #define REQ_BUF_SIZE        256
00047 #define RECV_BUF_SIZE       1024
00048 
00049 static char g_request_buffer[MAX_THREADS][REQ_BUF_SIZE]; // the default request is 65bytes long.
00050 static char g_receive_buffer[MAX_THREADS * RECV_BUF_SIZE];
00051 
00052 static volatile bool event_fired[MAX_THREADS] = { };
00053 
00054 static void socket_event_0(void) { event_fired[0] = true; }
00055 static void socket_event_1(void) { event_fired[1] = true; }
00056 static void socket_event_2(void) { event_fired[2] = true; }
00057 static void socket_event_3(void) { event_fired[3] = true; }
00058 static void socket_event_4(void) { event_fired[4] = true; }
00059 
00060 
00061 size_t download_test(NetworkInterface* interface, const unsigned char* data, size_t data_length, size_t buff_size, uint32_t thread_id) {
00062     int result = -1;
00063 
00064     TEST_ASSERT_MESSAGE(MAX_THREADS > thread_id, "Unsupported thread ID");
00065     TEST_ASSERT_MESSAGE((MAX_THREADS * RECV_BUF_SIZE) >= buff_size, "Cannot test with the requested buffer size");
00066 
00067     /* setup TCP socket */
00068     TCPSocket tcpsocket(interface);
00069 
00070     for (int tries = 0; tries < MAX_RETRIES; tries++) {
00071         result = tcpsocket.connect(dl_host, 80);
00072         TEST_ASSERT_MESSAGE(result != NSAPI_ERROR_NO_SOCKET, "out of sockets");
00073 
00074         if (result == 0) {
00075             break;
00076         }
00077         ThisThread::sleep_for(1000);
00078         printf("[NET-%d] Connection failed. Retry %d of %d\r\n", thread_id, tries, MAX_RETRIES);
00079     }
00080     TEST_ASSERT_EQUAL_INT_MESSAGE(0, result, "failed to connect");
00081 
00082     if (thread_id == 0) {
00083         // technically this is non-threaded mode
00084         tcpsocket.sigio(socket_event_0);
00085     } else if (thread_id == 1) {
00086         tcpsocket.sigio(socket_event_1);
00087     } else if (thread_id == 2) {
00088         tcpsocket.sigio(socket_event_2);
00089     } else if (thread_id == 3) {
00090         tcpsocket.sigio(socket_event_3);
00091     } else if (thread_id == 4) {
00092         tcpsocket.sigio(socket_event_4);
00093     } else {
00094         TEST_ASSERT_MESSAGE(0, "wrong thread id");
00095     }
00096     printf("[NET-%d] Registered socket callback function\r\n", thread_id);
00097     event_fired[thread_id] = false;
00098 
00099     /* setup request */
00100     char *request = g_request_buffer[thread_id];
00101 
00102     /* construct request */
00103     size_t req_len = snprintf(request, REQ_BUF_SIZE-1, req_template, dl_path, dl_host);
00104     request[req_len] = 0;
00105     printf("[NET-%d] Request header (%u): %s\r\n", thread_id, req_len, request);
00106 
00107     /* send request to server */
00108     result = tcpsocket.send(request, req_len);
00109     TEST_ASSERT_EQUAL_INT_MESSAGE(req_len, result, "failed to send");
00110 
00111     /* read response */
00112     char* receive_buffer = &g_receive_buffer[thread_id * RECV_BUF_SIZE];
00113 
00114     tcpsocket.set_blocking(false);
00115     printf("[NET-%d] Non-blocking socket mode set\r\n", thread_id);
00116 
00117     size_t received_bytes = 0;
00118     int body_index = -1;
00119 
00120     float speed;
00121     float percent;
00122     uint32_t time_left;
00123     Timer timer;
00124     timer.start();
00125 
00126     /* loop until all expected bytes have been received */
00127     while (received_bytes < data_length) {
00128         /* wait for async event */
00129         while(!event_fired[thread_id]) {
00130             if (thread_id > 0) {
00131                 ThisThread::yield();
00132             }
00133         }
00134         event_fired[thread_id] = false;
00135 
00136         /* loop until all data has been read from socket */
00137         do {
00138             result = tcpsocket.recv(receive_buffer, buff_size);
00139             TEST_ASSERT_MESSAGE((result == NSAPI_ERROR_WOULD_BLOCK) || (result >= 0),
00140                 "failed to read socket");
00141 
00142             if (result > 0) {
00143                 /* skip HTTP header */
00144                 if (body_index < 0) {
00145                     /* note that there are no required Response headers and their length may greatly vary */
00146                     std::string header(receive_buffer, result);
00147                     body_index = header.find("\r\n\r\n");
00148                     if (body_index < 0) {
00149                         continue;
00150                     } else {
00151                         printf("[NET-%d] Found body index: %d\r\n", thread_id, body_index);
00152 
00153                         /* remove header before comparison */
00154                         memmove(receive_buffer, &receive_buffer[body_index + 4], result - body_index - 4);
00155 
00156                         TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(data, receive_buffer, result - body_index - 4,
00157                             "character mismatch in header");
00158 
00159                         received_bytes += (result - body_index - 4);
00160                     }
00161                 } else {
00162                     TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(&data[received_bytes], receive_buffer, result,
00163                         "character mismatch in body");
00164 
00165                     received_bytes += result;
00166                 }
00167 
00168                 speed = float(received_bytes) / timer.read();
00169                 percent = float(received_bytes) * 100 / float(data_length);
00170                 time_left = (data_length - received_bytes) / speed;
00171                 printf("[NET-%d] Received bytes: %u, (%.2f%%, %.2fKB/s, ETA: %02d:%02d:%02d)\r\n",
00172                     thread_id, received_bytes, percent, speed / 1024,
00173                     time_left / 3600, (time_left / 60) % 60, time_left % 60);
00174             }
00175         }
00176         while ((result > 0) && (received_bytes < data_length));
00177     }
00178 
00179     TEST_ASSERT_MESSAGE(body_index >= 0, "failed to find body");
00180 
00181     timer.stop();
00182     float f_received_bytes = float(received_bytes);
00183     printf("[NET-%d] Downloaded: %.2fKB (%.2fKB/s, %.2f secs)\r\n", thread_id,
00184            f_received_bytes / 1024.,
00185            f_received_bytes / (timer.read() * 1024.),
00186            timer.read());
00187 
00188     return received_bytes;
00189 }
00190