Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of ublox-at-cellular-interface by
main.cpp
00001 #include "UbloxATCellularInterface.h" 00002 #include "greentea-client/test_env.h" 00003 #include "unity.h" 00004 #include "utest.h" 00005 #include "UDPSocket.h" 00006 #ifdef FEATURE_COMMON_PAL 00007 #include "mbed_trace.h" 00008 #define TRACE_GROUP "TEST" 00009 #else 00010 #define tr_debug(format, ...) debug(format "\n", ## __VA_ARGS__) 00011 #define tr_info(format, ...) debug(format "\n", ## __VA_ARGS__) 00012 #define tr_warn(format, ...) debug(format "\n", ## __VA_ARGS__) 00013 #define tr_error(format, ...) debug(format "\n", ## __VA_ARGS__) 00014 #endif 00015 00016 using namespace utest::v1; 00017 00018 // IMPORTANT!!! if you make a change to the tests here you should 00019 // check whether the same change should be made to the tests under 00020 // the PPP interface. 00021 00022 // NOTE: these test are only as reliable as UDP across the internet 00023 // over a radio link. The tests expect an NTP server to respond 00024 // to UDP packets and, if configured, an echo server to respond 00025 // to UDP packets. This simply may not happen. Please be patient. 00026 00027 // ---------------------------------------------------------------- 00028 // COMPILE-TIME MACROS 00029 // ---------------------------------------------------------------- 00030 00031 // These macros can be overridden with an mbed_app.json file and 00032 // contents of the following form: 00033 // 00034 //{ 00035 // "config": { 00036 // "default-pin": { 00037 // "value": "\"1234\"" 00038 // } 00039 //} 00040 // 00041 // See the template_mbed_app.txt in this directory for a fuller example. 00042 00043 // Whether debug trace is on 00044 #ifndef MBED_CONF_APP_DEBUG_ON 00045 # define MBED_CONF_APP_DEBUG_ON false 00046 #endif 00047 00048 // Run the SIM change tests, which require the DEFAULT_PIN 00049 // above to be correct for the board on which the test 00050 // is being run (and the SIM PIN to be disabled before tests run). 00051 #ifndef MBED_CONF_APP_RUN_SIM_PIN_CHANGE_TESTS 00052 # define MBED_CONF_APP_RUN_SIM_PIN_CHANGE_TESTS 0 00053 #endif 00054 00055 #if MBED_CONF_APP_RUN_SIM_PIN_CHANGE_TESTS 00056 # ifndef MBED_CONF_APP_DEFAULT_PIN 00057 # error "MBED_CONF_APP_DEFAULT_PIN must be defined to run the SIM tests" 00058 # endif 00059 # ifndef MBED_CONF_APP_ALT_PIN 00060 # error "MBED_CONF_APP_ALT_PIN must be defined to run the SIM tests" 00061 # endif 00062 # ifndef MBED_CONF_APP_INCORRECT_PIN 00063 # error "MBED_CONF_APP_INCORRECT_PIN must be defined to run the SIM tests" 00064 # endif 00065 #endif 00066 00067 // The credentials of the SIM in the board. 00068 #ifndef MBED_CONF_APP_DEFAULT_PIN 00069 // Note: if PIN is enabled on your SIM, or you wish to run the SIM PIN change 00070 // tests, you must define the PIN for your SIM (see note above on using 00071 // mbed_app.json to do so). 00072 # define MBED_CONF_APP_DEFAULT_PIN "0000" 00073 #endif 00074 #ifndef MBED_CONF_APP_APN 00075 # define MBED_CONF_APP_APN NULL 00076 #endif 00077 #ifndef MBED_CONF_APP_USERNAME 00078 # define MBED_CONF_APP_USERNAME NULL 00079 #endif 00080 #ifndef MBED_CONF_APP_PASSWORD 00081 # define MBED_CONF_APP_PASSWORD NULL 00082 #endif 00083 00084 // Alternate PIN to use during pin change testing 00085 #ifndef MBED_CONF_APP_ALT_PIN 00086 # define MBED_CONF_APP_ALT_PIN "9876" 00087 #endif 00088 00089 // A PIN that is definitely incorrect 00090 #ifndef MBED_CONF_APP_INCORRECT_PIN 00091 # define MBED_CONF_APP_INCORRECT_PIN "1530" 00092 #endif 00093 00094 // Servers and ports 00095 #ifdef MBED_CONF_APP_ECHO_SERVER 00096 # ifndef MBED_CONF_APP_ECHO_UDP_PORT 00097 # error "MBED_CONF_APP_ECHO_UDP_PORT (the port on which your echo server echoes UDP packets) must be defined" 00098 # endif 00099 # ifndef MBED_CONF_APP_ECHO_TCP_PORT 00100 # error "MBED_CONF_APP_ECHO_TCP_PORT (the port on which your echo server echoes TCP packets) must be defined" 00101 # endif 00102 #endif 00103 00104 #ifndef MBED_CONF_APP_NTP_SERVER 00105 # define MBED_CONF_APP_NTP_SERVER "2.pool.ntp.org" 00106 #else 00107 # ifndef MBED_CONF_APP_NTP_PORT 00108 # error "MBED_CONF_APP_NTP_PORT must be defined if MBED_CONF_APP_NTP_SERVER is defined" 00109 # endif 00110 #endif 00111 #ifndef MBED_CONF_APP_NTP_PORT 00112 # define MBED_CONF_APP_NTP_PORT 123 00113 #endif 00114 00115 #ifndef MBED_CONF_APP_LOCAL_PORT 00116 # define MBED_CONF_APP_LOCAL_PORT 15 00117 #endif 00118 00119 // UDP packet size limit for testing 00120 #ifndef MBED_CONF_APP_UDP_MAX_PACKET_SIZE 00121 # define MBED_CONF_APP_UDP_MAX_PACKET_SIZE 1024 00122 #endif 00123 00124 // The maximum size of UDP data fragmented across 00125 // multiple packets 00126 #ifndef MBED_CONF_APP_UDP_MAX_FRAG_PACKET_SIZE 00127 # define MBED_CONF_APP_UDP_MAX_FRAG_PACKET_SIZE 1500 00128 #endif 00129 00130 // TCP packet size limit for testing 00131 #ifndef MBED_CONF_APP_MBED_CONF_APP_TCP_MAX_PACKET_SIZE 00132 # define MBED_CONF_APP_TCP_MAX_PACKET_SIZE 1500 00133 #endif 00134 00135 // The number of retries for UDP exchanges 00136 #define NUM_UDP_RETRIES 5 00137 00138 // How long to wait for stuff to travel in the async echo tests 00139 #define ASYNC_TEST_WAIT_TIME 10000 00140 00141 // The maximum number of sockets that can be open at one time 00142 #define MAX_NUM_SOCKETS 7 00143 00144 // ---------------------------------------------------------------- 00145 // PRIVATE VARIABLES 00146 // ---------------------------------------------------------------- 00147 00148 #ifdef FEATURE_COMMON_PAL 00149 // Lock for debug prints 00150 static Mutex mtx; 00151 #endif 00152 00153 // An instance of the cellular interface 00154 static UbloxATCellularInterface *interface = 00155 new UbloxATCellularInterface(MDMTXD, MDMRXD, 00156 MBED_CONF_UBLOX_CELL_BAUD_RATE, 00157 MBED_CONF_APP_DEBUG_ON); 00158 00159 // Connection flag 00160 static bool connection_has_gone_down = false; 00161 00162 // Data to exchange 00163 static const char send_data[] = "_____0000:0123456789012345678901234567890123456789" 00164 "01234567890123456789012345678901234567890123456789" 00165 "_____0100:0123456789012345678901234567890123456789" 00166 "01234567890123456789012345678901234567890123456789" 00167 "_____0200:0123456789012345678901234567890123456789" 00168 "01234567890123456789012345678901234567890123456789" 00169 "_____0300:0123456789012345678901234567890123456789" 00170 "01234567890123456789012345678901234567890123456789" 00171 "_____0400:0123456789012345678901234567890123456789" 00172 "01234567890123456789012345678901234567890123456789" 00173 "_____0500:0123456789012345678901234567890123456789" 00174 "01234567890123456789012345678901234567890123456789" 00175 "_____0600:0123456789012345678901234567890123456789" 00176 "01234567890123456789012345678901234567890123456789" 00177 "_____0700:0123456789012345678901234567890123456789" 00178 "01234567890123456789012345678901234567890123456789" 00179 "_____0800:0123456789012345678901234567890123456789" 00180 "01234567890123456789012345678901234567890123456789" 00181 "_____0900:0123456789012345678901234567890123456789" 00182 "01234567890123456789012345678901234567890123456789" 00183 "_____1000:0123456789012345678901234567890123456789" 00184 "01234567890123456789012345678901234567890123456789" 00185 "_____1100:0123456789012345678901234567890123456789" 00186 "01234567890123456789012345678901234567890123456789" 00187 "_____1200:0123456789012345678901234567890123456789" 00188 "01234567890123456789012345678901234567890123456789" 00189 "_____1300:0123456789012345678901234567890123456789" 00190 "01234567890123456789012345678901234567890123456789" 00191 "_____1400:0123456789012345678901234567890123456789" 00192 "01234567890123456789012345678901234567890123456789" 00193 "_____1500:0123456789012345678901234567890123456789" 00194 "01234567890123456789012345678901234567890123456789" 00195 "_____1600:0123456789012345678901234567890123456789" 00196 "01234567890123456789012345678901234567890123456789" 00197 "_____1700:0123456789012345678901234567890123456789" 00198 "01234567890123456789012345678901234567890123456789" 00199 "_____1800:0123456789012345678901234567890123456789" 00200 "01234567890123456789012345678901234567890123456789" 00201 "_____1900:0123456789012345678901234567890123456789" 00202 "01234567890123456789012345678901234567890123456789" 00203 "_____2000:0123456789012345678901234567890123456789" 00204 "01234567890123456789012345678901234567890123456789"; 00205 00206 // ---------------------------------------------------------------- 00207 // PRIVATE FUNCTIONS 00208 // ---------------------------------------------------------------- 00209 00210 #ifdef FEATURE_COMMON_PAL 00211 // Locks for debug prints 00212 static void lock() 00213 { 00214 mtx.lock(); 00215 } 00216 00217 static void unlock() 00218 { 00219 mtx.unlock(); 00220 } 00221 #endif 00222 00223 // Callback in case the connection goes down 00224 static void connection_down_cb(nsapi_error_t err) 00225 { 00226 connection_has_gone_down = true; 00227 } 00228 00229 #ifdef MBED_CONF_APP_ECHO_SERVER 00230 // Make sure that size is greater than 0 and no more than limit, 00231 // useful since, when moduloing a very large number number, 00232 // compilers sometimes screw up and produce a small *negative* 00233 // number. Who knew? For example, GCC decided that 00234 // 492318453 (0x1d582ef5) modulo 508 was -47 (0xffffffd1). 00235 static int fix (int size, int limit) 00236 { 00237 if (size <= 0) { 00238 size = limit / 2; // better than 1 00239 } else if (size > limit) { 00240 size = limit; 00241 } 00242 00243 return size; 00244 } 00245 00246 // Do a UDP socket echo test to a given host of a given packet size 00247 static void do_udp_echo(UDPSocket *sock, SocketAddress *host_address, int size) 00248 { 00249 bool success = false; 00250 void * recv_data = malloc (size); 00251 SocketAddress sender_address; 00252 TEST_ASSERT(recv_data != NULL); 00253 00254 // Retry this a few times, don't want to fail due to a flaky link 00255 for (int x = 0; !success && (x < NUM_UDP_RETRIES); x++) { 00256 tr_debug("Echo testing UDP packet size %d byte(s), try %d.", size, x + 1); 00257 if ((sock->sendto(*host_address, (void*) send_data, size) == size) && 00258 (sock->recvfrom(&sender_address, recv_data, size) == size)) { 00259 TEST_ASSERT (memcmp(send_data, recv_data, size) == 0); 00260 TEST_ASSERT (strcmp(sender_address.get_ip_address(), host_address->get_ip_address()) == 0); 00261 TEST_ASSERT (sender_address.get_port() == host_address->get_port()); 00262 success = true; 00263 } 00264 } 00265 TEST_ASSERT (success); 00266 TEST_ASSERT(!connection_has_gone_down); 00267 00268 free (recv_data); 00269 } 00270 00271 // The asynchronous callback 00272 static void async_cb(bool *callback_triggered) 00273 { 00274 00275 TEST_ASSERT (callback_triggered != NULL); 00276 *callback_triggered = true; 00277 } 00278 00279 // Do a UDP echo but using the asynchronous interface; we can exchange 00280 // packets longer in size than one UDP packet this way 00281 static void do_udp_echo_async(UDPSocket *sock, SocketAddress *host_address, 00282 int size, bool *callback_triggered) 00283 { 00284 void * recv_data = malloc (size); 00285 int recv_size = 0; 00286 SocketAddress sender_address; 00287 Timer timer; 00288 int x, y, z; 00289 TEST_ASSERT(recv_data != NULL); 00290 00291 *callback_triggered = false; 00292 for (y = 0; (recv_size < size) && (y < NUM_UDP_RETRIES); y++) { 00293 tr_debug("Echo testing UDP packet size %d byte(s) async, try %d.", size, y + 1); 00294 recv_size = 0; 00295 // Retry this a few times, don't want to fail due to a flaky link 00296 if (sock->sendto(*host_address, (void *) send_data, size) == size) { 00297 // Wait for all the echoed data to arrive 00298 timer.start(); 00299 while ((recv_size < size) && (timer.read_ms() < ASYNC_TEST_WAIT_TIME)) { 00300 if (*callback_triggered) { 00301 *callback_triggered = false; 00302 x = sock->recvfrom(&sender_address, (char *) recv_data + recv_size, size); 00303 if (x > 0) { 00304 recv_size += x; 00305 } 00306 tr_debug("%d byte(s) echoed back so far, %d to go.", recv_size, size - recv_size); 00307 TEST_ASSERT(strcmp(sender_address.get_ip_address(), host_address->get_ip_address()) == 0); 00308 TEST_ASSERT(sender_address.get_port() == host_address->get_port()); 00309 } 00310 wait_ms(10); 00311 } 00312 timer.stop(); 00313 timer.reset(); 00314 00315 // If everything arrived back, check it's the same as we sent 00316 if (recv_size == size) { 00317 z = memcmp(send_data, recv_data, size); 00318 if (z != 0) { 00319 tr_debug("WARNING: mismatch, retrying"); 00320 tr_debug("Sent %d, |%*.*s|", size, size, size, send_data); 00321 tr_debug("Rcvd %d, |%*.*s|", size, size, size, (char *) recv_data); 00322 // If things don't match, it could be due to data loss (this is UDP 00323 // you know...), so set recv_size to 0 to cause another try 00324 recv_size = 0; 00325 } 00326 } 00327 } 00328 } 00329 00330 TEST_ASSERT(recv_size == size); 00331 TEST_ASSERT(!connection_has_gone_down); 00332 00333 free (recv_data); 00334 } 00335 00336 // Send an entire TCP data buffer until done 00337 static int sendAll(TCPSocket *sock, const char *data, int size) 00338 { 00339 int x; 00340 int count = 0; 00341 Timer timer; 00342 00343 timer.start(); 00344 while ((count < size) && (timer.read_ms() < 10000)) { 00345 x = sock->send(data + count, size - count); 00346 if (x > 0) { 00347 count += x; 00348 tr_debug("%d byte(s) sent, %d left to send.", count, size - count); 00349 } 00350 wait_ms(10); 00351 } 00352 timer.stop(); 00353 00354 return count; 00355 } 00356 00357 // Do a TCP echo but using the asynchronous interface 00358 static void do_tcp_echo_async(TCPSocket *sock, int size, bool *callback_triggered) 00359 { 00360 void * recv_data = malloc (size); 00361 int recv_size = 0; 00362 int x, y; 00363 Timer timer; 00364 TEST_ASSERT(recv_data != NULL); 00365 00366 *callback_triggered = false; 00367 tr_debug("Echo testing TCP packet size %d byte(s) async.", size); 00368 TEST_ASSERT (sendAll(sock, send_data, size) == size); 00369 00370 // Wait for all the echoed data to arrive 00371 timer.start(); 00372 while ((recv_size < size) && (timer.read_ms() < ASYNC_TEST_WAIT_TIME)) { 00373 if (*callback_triggered) { 00374 *callback_triggered = false; 00375 x = sock->recv((char *) recv_data + recv_size, size); 00376 TEST_ASSERT(x > 0); 00377 recv_size += x; 00378 tr_debug("%d byte(s) echoed back so far, %d to go.", recv_size, size - recv_size); 00379 } 00380 wait_ms(10); 00381 } 00382 TEST_ASSERT(recv_size == size); 00383 y = memcmp(send_data, recv_data, size); 00384 if (y != 0) { 00385 tr_debug("Sent %d, |%*.*s|", size, size, size, send_data); 00386 tr_debug("Rcvd %d, |%*.*s|", size, size, size, (char *) recv_data); 00387 TEST_ASSERT(false); 00388 } 00389 timer.stop(); 00390 00391 TEST_ASSERT(!connection_has_gone_down); 00392 00393 free (recv_data); 00394 } 00395 #endif 00396 00397 // Get NTP time from a socket 00398 static void do_ntp_sock (UDPSocket *sock, SocketAddress ntp_address) 00399 { 00400 char ntp_values[48] = { 0 }; 00401 time_t timestamp = 0; 00402 struct tm *localTime; 00403 char timeString[25]; 00404 time_t TIME1970 = 2208988800U; 00405 int len; 00406 bool comms_done = false; 00407 00408 ntp_values[0] = '\x1b'; 00409 00410 // Retry this a few times, don't want to fail due to a flaky link 00411 for (unsigned int x = 0; !comms_done && (x < NUM_UDP_RETRIES); x++) { 00412 sock->sendto(ntp_address, (void*) ntp_values, sizeof(ntp_values)); 00413 len = sock->recvfrom(&ntp_address, (void*) ntp_values, sizeof(ntp_values)); 00414 if (len > 0) { 00415 comms_done = true; 00416 } 00417 } 00418 TEST_ASSERT (comms_done); 00419 00420 tr_debug("UDP: %d byte(s) returned by NTP server.", len); 00421 if (len >= 43) { 00422 timestamp |= ((int) *(ntp_values + 40)) << 24; 00423 timestamp |= ((int) *(ntp_values + 41)) << 16; 00424 timestamp |= ((int) *(ntp_values + 42)) << 8; 00425 timestamp |= ((int) *(ntp_values + 43)); 00426 timestamp -= TIME1970; 00427 srand (timestamp); 00428 tr_debug("srand() called"); 00429 localTime = localtime(×tamp); 00430 if (localTime) { 00431 if (strftime(timeString, sizeof(timeString), "%a %b %d %H:%M:%S %Y", localTime) > 0) { 00432 printf("NTP timestamp is %s.\n", timeString); 00433 } 00434 } 00435 } 00436 } 00437 00438 // Get NTP time 00439 static void do_ntp(UbloxATCellularInterface *interface) 00440 { 00441 UDPSocket sock; 00442 SocketAddress host_address; 00443 00444 TEST_ASSERT(sock.open(interface) == 0) 00445 00446 TEST_ASSERT(interface->gethostbyname(MBED_CONF_APP_NTP_SERVER, &host_address) == 0); 00447 host_address.set_port(MBED_CONF_APP_NTP_PORT); 00448 00449 tr_debug("UDP: NIST server %s address: %s on port %d.", MBED_CONF_APP_NTP_SERVER, 00450 host_address.get_ip_address(), host_address.get_port()); 00451 00452 sock.set_timeout(10000); 00453 00454 do_ntp_sock(&sock, host_address); 00455 00456 sock.close(); 00457 } 00458 00459 // Use a connection, checking that it is good 00460 static void use_connection(UbloxATCellularInterface *interface) 00461 { 00462 const char * ip_address = interface->get_ip_address(); 00463 const char * net_mask = interface->get_netmask(); 00464 const char * gateway = interface->get_gateway(); 00465 00466 TEST_ASSERT(interface->is_connected()); 00467 00468 TEST_ASSERT(ip_address != NULL); 00469 tr_debug ("IP address %s.", ip_address); 00470 TEST_ASSERT(net_mask == NULL); 00471 tr_debug ("Net mask %s.", net_mask); 00472 TEST_ASSERT(gateway != NULL); 00473 tr_debug ("Gateway %s.", gateway); 00474 00475 do_ntp(interface); 00476 TEST_ASSERT(!connection_has_gone_down); 00477 } 00478 00479 // Drop a connection and check that it has dropped 00480 static void drop_connection(UbloxATCellularInterface *interface) 00481 { 00482 TEST_ASSERT(interface->disconnect() == 0); 00483 TEST_ASSERT(connection_has_gone_down); 00484 connection_has_gone_down = false; 00485 TEST_ASSERT(!interface->is_connected()); 00486 } 00487 00488 // ---------------------------------------------------------------- 00489 // TESTS 00490 // ---------------------------------------------------------------- 00491 00492 // Call srand() using the NTP server 00493 void test_set_randomise() { 00494 UDPSocket sock; 00495 SocketAddress host_address; 00496 00497 TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 00498 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00499 do_ntp(interface); 00500 TEST_ASSERT(!connection_has_gone_down); 00501 drop_connection(interface); 00502 } 00503 00504 #ifdef MBED_CONF_APP_ECHO_SERVER 00505 00506 // Test UDP data exchange 00507 void test_udp_echo() { 00508 UDPSocket sock; 00509 SocketAddress host_address; 00510 SocketAddress local_address; 00511 int x; 00512 int size; 00513 00514 TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 00515 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00516 00517 TEST_ASSERT(interface->gethostbyname(MBED_CONF_APP_ECHO_SERVER, &host_address) == 0); 00518 host_address.set_port(MBED_CONF_APP_ECHO_UDP_PORT); 00519 00520 tr_debug("UDP: Server %s address: %s on port %d.", MBED_CONF_APP_ECHO_SERVER, 00521 host_address.get_ip_address(), host_address.get_port()); 00522 00523 TEST_ASSERT(sock.open(interface) == 0) 00524 00525 // Do a bind, just for the helluvit 00526 local_address.set_port(MBED_CONF_APP_LOCAL_PORT); 00527 TEST_ASSERT(sock.bind(local_address) == 0); 00528 00529 sock.set_timeout(10000); 00530 00531 // Test min, max, and some random sizes in-between 00532 do_udp_echo(&sock, &host_address, 1); 00533 do_udp_echo(&sock, &host_address, MBED_CONF_APP_UDP_MAX_PACKET_SIZE); 00534 for (x = 0; x < 10; x++) { 00535 size = (rand() % MBED_CONF_APP_UDP_MAX_PACKET_SIZE) + 1; 00536 size = fix(size, MBED_CONF_APP_UDP_MAX_PACKET_SIZE); 00537 do_udp_echo(&sock, &host_address, size); 00538 } 00539 00540 sock.close(); 00541 drop_connection(interface); 00542 tr_debug("%d UDP packets of size up to %d byte(s) echoed successfully.", 00543 x, MBED_CONF_APP_UDP_MAX_PACKET_SIZE); 00544 } 00545 00546 // Test many different sizes of UDP data arriving at once 00547 void test_udp_echo_recv_sizes() { 00548 UDPSocket sock; 00549 SocketAddress host_address; 00550 int x, y, z; 00551 int size; 00552 int tries = 0; 00553 unsigned int offset; 00554 char * recv_data; 00555 bool packetLoss; 00556 bool sendSuccess; 00557 Timer timer; 00558 00559 interface->deinit(); 00560 TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 00561 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00562 00563 TEST_ASSERT(interface->gethostbyname(MBED_CONF_APP_ECHO_SERVER, &host_address) == 0); 00564 host_address.set_port(MBED_CONF_APP_ECHO_UDP_PORT); 00565 00566 tr_debug("UDP: Server %s address: %s on port %d.", MBED_CONF_APP_ECHO_SERVER, 00567 host_address.get_ip_address(), host_address.get_port()); 00568 00569 TEST_ASSERT(sock.open(interface) == 0) 00570 00571 do { 00572 tr_debug("--- UDP packet size test, test try %d, flushing input buffers", tries + 1); 00573 // First of all, clear any junk from the socket 00574 sock.set_timeout(1000); 00575 recv_data = (char *) malloc (MBED_CONF_APP_UDP_MAX_PACKET_SIZE); 00576 TEST_ASSERT(recv_data != NULL); 00577 while (sock.recvfrom(&host_address, (void *) recv_data, MBED_CONF_APP_UDP_MAX_PACKET_SIZE) > 0) { 00578 // Throw it away 00579 } 00580 free (recv_data); 00581 00582 sock.set_timeout(10000); 00583 00584 // Throw random sized UDP packets up... 00585 x = 0; 00586 offset = 0; 00587 while (offset < sizeof (send_data)) { 00588 size = (rand() % (MBED_CONF_APP_UDP_MAX_PACKET_SIZE / 2)) + 1; 00589 size = fix(size, MBED_CONF_APP_UDP_MAX_PACKET_SIZE / 2); 00590 if (offset + size > sizeof (send_data)) { 00591 size = sizeof (send_data) - offset; 00592 } 00593 sendSuccess = false; 00594 for (y = 0; !sendSuccess && (y < NUM_UDP_RETRIES); y++) { 00595 tr_debug("Sending UDP packet number %d, size %d byte(s), send try %d.", x + 1, size, y + 1); 00596 if (sock.sendto(host_address, (void *) (send_data + offset), size) == size) { 00597 sendSuccess = true; 00598 offset += size; 00599 } 00600 } 00601 TEST_ASSERT(sendSuccess); 00602 x++; 00603 } 00604 tr_debug("--- All UDP packets sent"); 00605 00606 // ...and capture them all again afterwards 00607 recv_data = (char *) malloc (sizeof (send_data)); 00608 TEST_ASSERT(recv_data != NULL); 00609 memset (recv_data, 0, sizeof (send_data)); 00610 size = 0; 00611 y = 0; 00612 packetLoss = false; 00613 timer.start(); 00614 while ((size < (int) sizeof (send_data)) && (timer.read_ms() < 10000)) { 00615 y = sock.recvfrom(&host_address, (void *) (recv_data + size), sizeof (send_data) - size); 00616 if (y > 0) { 00617 size += y; 00618 } 00619 } 00620 timer.stop(); 00621 timer.reset(); 00622 tr_debug( "--- Either received everything back or timed out waiting"); 00623 00624 // Check that we reassembled everything correctly 00625 if (size == sizeof (send_data)) { 00626 for (x = 0; ((*(recv_data + x) == *(send_data + x))) && (x < (int) sizeof (send_data)); x++) { 00627 } 00628 if (x != sizeof (send_data)) { 00629 y = x - 5; 00630 if (y < 0) { 00631 y = 0; 00632 } 00633 z = 10; 00634 if (y + z > (int) sizeof (send_data)) { 00635 z = sizeof(send_data) - y; 00636 } 00637 tr_debug(" --- Difference at character %d (send \"%*.*s\", recv \"%*.*s\")", 00638 x + 1, z, z, send_data + y, z, z, recv_data + y); 00639 packetLoss = true; 00640 } 00641 } else { 00642 tr_debug(" --- %d bytes missing (%d bytes received when %d were expected))", 00643 sizeof (send_data) - size, size, sizeof (send_data)); 00644 packetLoss = true; 00645 } 00646 free (recv_data); 00647 tries++; 00648 } while (packetLoss && (tries < NUM_UDP_RETRIES)); 00649 00650 TEST_ASSERT(!packetLoss); 00651 TEST_ASSERT(!connection_has_gone_down); 00652 sock.close(); 00653 drop_connection(interface); 00654 } 00655 00656 // Test UDP data exchange via the asynchronous sigio() mechanism 00657 void test_udp_echo_async() { 00658 UDPSocket sock; 00659 SocketAddress host_address; 00660 SocketAddress local_address; 00661 bool callback_triggered = false; 00662 int x; 00663 int size; 00664 00665 interface->deinit(); 00666 TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 00667 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00668 00669 TEST_ASSERT(interface->gethostbyname(MBED_CONF_APP_ECHO_SERVER, &host_address) == 0); 00670 host_address.set_port(MBED_CONF_APP_ECHO_UDP_PORT); 00671 00672 tr_debug("UDP: Server %s address: %s on port %d.", MBED_CONF_APP_ECHO_SERVER, 00673 host_address.get_ip_address(), host_address.get_port()); 00674 00675 TEST_ASSERT(sock.open(interface) == 0) 00676 00677 // Set up the async callback and set the timeout to zero 00678 sock.sigio(callback(async_cb, &callback_triggered)); 00679 sock.set_timeout(0); 00680 00681 // Test min, max, and some random sizes in-between 00682 // and this time allow the UDP packets to be fragmented 00683 do_udp_echo_async(&sock, &host_address, 1, &callback_triggered); 00684 do_udp_echo_async(&sock, &host_address, MBED_CONF_APP_UDP_MAX_FRAG_PACKET_SIZE, 00685 &callback_triggered); 00686 for (x = 0; x < 10; x++) { 00687 size = (rand() % MBED_CONF_APP_UDP_MAX_FRAG_PACKET_SIZE) + 1; 00688 size = fix(size, MBED_CONF_APP_UDP_MAX_FRAG_PACKET_SIZE); 00689 do_udp_echo_async(&sock, &host_address, size, &callback_triggered); 00690 } 00691 00692 sock.close(); 00693 00694 drop_connection(interface); 00695 00696 tr_debug("%d UDP packets of size up to %d byte(s) echoed asynchronously and successfully.", 00697 x, MBED_CONF_APP_UDP_MAX_FRAG_PACKET_SIZE); 00698 } 00699 00700 // Test many different sizes of TCP data arriving at once 00701 void test_tcp_echo_recv_sizes() { 00702 TCPSocket sock; 00703 SocketAddress host_address; 00704 int x, y, z; 00705 int size; 00706 unsigned int offset; 00707 char * recv_data; 00708 Timer timer; 00709 00710 interface->deinit(); 00711 TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 00712 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00713 00714 TEST_ASSERT(interface->gethostbyname(MBED_CONF_APP_ECHO_SERVER, &host_address) == 0); 00715 host_address.set_port(MBED_CONF_APP_ECHO_TCP_PORT); 00716 00717 tr_debug("TCP: Server %s address: %s on port %d.", MBED_CONF_APP_ECHO_SERVER, 00718 host_address.get_ip_address(), host_address.get_port()); 00719 00720 TEST_ASSERT(sock.open(interface) == 0) 00721 00722 TEST_ASSERT(sock.connect(host_address) == 0); 00723 00724 sock.set_timeout(10000); 00725 00726 // Throw random sized TCP packets up... 00727 x = 0; 00728 offset = 0; 00729 while (offset < sizeof (send_data)) { 00730 size = (rand() % (MBED_CONF_APP_UDP_MAX_PACKET_SIZE / 2)) + 1; 00731 size = fix(size, MBED_CONF_APP_UDP_MAX_PACKET_SIZE / 2); 00732 if (offset + size > sizeof (send_data)) { 00733 size = sizeof (send_data) - offset; 00734 } 00735 tr_debug("Sending TCP packet number %d, size %d byte(s).", x + 1, size); 00736 TEST_ASSERT(sendAll(&sock, (send_data + offset), size) == size); 00737 offset += size; 00738 x++; 00739 } 00740 00741 // ...and capture them all again afterwards 00742 recv_data = (char *) malloc (sizeof (send_data)); 00743 TEST_ASSERT(recv_data != NULL); 00744 memset (recv_data, 0, sizeof (send_data)); 00745 size = 0; 00746 x = 0; 00747 timer.start(); 00748 while ((size < (int) sizeof (send_data)) && (timer.read_ms() < 30000)) { 00749 y = sock.recv((void *) (recv_data + size), sizeof (send_data) - size); 00750 tr_debug("Received TCP packet number %d, size %d byte(s).", x, y); 00751 size += y; 00752 x++; 00753 } 00754 timer.stop(); 00755 timer.reset(); 00756 00757 // Check that we reassembled everything correctly 00758 for (x = 0; ((*(recv_data + x) == *(send_data + x))) && (x < (int) sizeof (send_data)); x++) { 00759 } 00760 if (x != sizeof (send_data)) { 00761 y = x - 5; 00762 if (y < 0) { 00763 y = 0; 00764 } 00765 z = 10; 00766 if (y + z > (int) sizeof (send_data)) { 00767 z = sizeof(send_data) - y; 00768 } 00769 tr_debug("Difference at character %d (send \"%*.*s\", recv \"%*.*s\")", 00770 x + 1, z, z, send_data + y, z, z, recv_data + y); 00771 TEST_ASSERT(false); 00772 } 00773 free (recv_data); 00774 00775 TEST_ASSERT(!connection_has_gone_down); 00776 sock.close(); 00777 drop_connection(interface); 00778 } 00779 00780 // Test TCP data exchange via the asynchronous sigio() mechanism 00781 void test_tcp_echo_async() { 00782 TCPSocket sock; 00783 SocketAddress host_address; 00784 bool callback_triggered = false; 00785 int x; 00786 int size; 00787 00788 interface->deinit(); 00789 TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 00790 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00791 00792 TEST_ASSERT(interface->gethostbyname(MBED_CONF_APP_ECHO_SERVER, &host_address) == 0); 00793 host_address.set_port(MBED_CONF_APP_ECHO_TCP_PORT); 00794 00795 tr_debug("TCP: Server %s address: %s on port %d.", MBED_CONF_APP_ECHO_SERVER, 00796 host_address.get_ip_address(), host_address.get_port()); 00797 00798 TEST_ASSERT(sock.open(interface) == 0) 00799 00800 // Set up the async callback and set the timeout to zero 00801 sock.sigio(callback(async_cb, &callback_triggered)); 00802 sock.set_timeout(0); 00803 00804 TEST_ASSERT(sock.connect(host_address) == 0); 00805 // Test min, max, and some random sizes in-between 00806 do_tcp_echo_async(&sock, 1, &callback_triggered); 00807 do_tcp_echo_async(&sock, MBED_CONF_APP_TCP_MAX_PACKET_SIZE, &callback_triggered); 00808 for (x = 0; x < 10; x++) { 00809 size = (rand() % MBED_CONF_APP_TCP_MAX_PACKET_SIZE) + 1; 00810 size = fix(size, MBED_CONF_APP_TCP_MAX_PACKET_SIZE); 00811 do_tcp_echo_async(&sock, size, &callback_triggered); 00812 } 00813 00814 sock.close(); 00815 00816 drop_connection(interface); 00817 00818 tr_debug("%d TCP packets of size up to %d byte(s) echoed asynchronously and successfully.", 00819 x, MBED_CONF_APP_TCP_MAX_PACKET_SIZE); 00820 } 00821 #endif 00822 00823 // Allocate max sockets 00824 void test_max_sockets() { 00825 UDPSocket sock[MAX_NUM_SOCKETS]; 00826 UDPSocket sockNone; 00827 SocketAddress host_address; 00828 00829 TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 00830 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00831 00832 TEST_ASSERT(interface->gethostbyname(MBED_CONF_APP_NTP_SERVER, &host_address) == 0); 00833 host_address.set_port(MBED_CONF_APP_NTP_PORT); 00834 00835 // Open the first socket and use it 00836 TEST_ASSERT(sock[0].open(interface) == 0) 00837 sock[0].set_timeout(10000); 00838 do_ntp_sock(&sock[0], host_address); 00839 00840 // Check that we stop being able to get sockets at the max number 00841 for (int x = 1; x < (int) (sizeof (sock) / sizeof (sock[0])); x++) { 00842 TEST_ASSERT(sock[x].open(interface) == 0) 00843 } 00844 TEST_ASSERT(sockNone.open(interface) < 0); 00845 00846 // Now use the last one 00847 sock[sizeof (sock) / sizeof (sock[0]) - 1].set_timeout(10000); 00848 do_ntp_sock(&sock[sizeof (sock) / sizeof (sock[0]) - 1], host_address); 00849 00850 // Close all of the sockets 00851 for (int x = 0; x < (int) (sizeof (sock) / sizeof (sock[0])); x++) { 00852 TEST_ASSERT(sock[x].close() == 0); 00853 } 00854 00855 drop_connection(interface); 00856 } 00857 00858 // Connect with credentials included in the connect request 00859 void test_connect_credentials() { 00860 00861 interface->deinit(); 00862 TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 00863 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00864 use_connection(interface); 00865 drop_connection(interface); 00866 } 00867 00868 // Test with credentials preset 00869 void test_connect_preset_credentials() { 00870 00871 interface->deinit(); 00872 TEST_ASSERT(interface->init(MBED_CONF_APP_DEFAULT_PIN)); 00873 interface->set_credentials(MBED_CONF_APP_APN, MBED_CONF_APP_USERNAME, 00874 MBED_CONF_APP_PASSWORD); 00875 TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN) == 0); 00876 use_connection(interface); 00877 drop_connection(interface); 00878 } 00879 00880 // Test adding and using a SIM pin, then removing it, using the pending 00881 // mechanism where the change doesn't occur until connect() is called 00882 void test_check_sim_pin_pending() { 00883 00884 interface->deinit(); 00885 00886 // Enable PIN checking (which will use the current PIN) 00887 // and also flag that the PIN should be changed to MBED_CONF_APP_ALT_PIN, 00888 // then try connecting 00889 interface->set_sim_pin_check(true); 00890 interface->set_new_sim_pin(MBED_CONF_APP_ALT_PIN); 00891 TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 00892 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00893 use_connection(interface); 00894 drop_connection(interface); 00895 interface->deinit(); 00896 00897 // Now change the PIN back to what it was before 00898 interface->set_new_sim_pin(MBED_CONF_APP_DEFAULT_PIN); 00899 TEST_ASSERT(interface->connect(MBED_CONF_APP_ALT_PIN, MBED_CONF_APP_APN, 00900 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00901 use_connection(interface); 00902 drop_connection(interface); 00903 interface->deinit(); 00904 00905 // Check that it was changed back, and this time 00906 // use the other way of entering the PIN 00907 interface->set_sim_pin(MBED_CONF_APP_DEFAULT_PIN); 00908 TEST_ASSERT(interface->connect(NULL, MBED_CONF_APP_APN, MBED_CONF_APP_USERNAME, 00909 MBED_CONF_APP_PASSWORD) == 0); 00910 use_connection(interface); 00911 drop_connection(interface); 00912 interface->deinit(); 00913 00914 // Remove PIN checking again and check that it no 00915 // longer matters what the PIN is 00916 interface->set_sim_pin_check(false); 00917 TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 00918 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00919 use_connection(interface); 00920 drop_connection(interface); 00921 interface->deinit(); 00922 TEST_ASSERT(interface->init(NULL)); 00923 TEST_ASSERT(interface->connect(MBED_CONF_APP_INCORRECT_PIN, MBED_CONF_APP_APN, 00924 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00925 use_connection(interface); 00926 drop_connection(interface); 00927 00928 // Put the SIM pin back to the correct value for any subsequent tests 00929 interface->set_sim_pin(MBED_CONF_APP_DEFAULT_PIN); 00930 } 00931 00932 // Test adding and using a SIM pin, then removing it, using the immediate 00933 // mechanism 00934 void test_check_sim_pin_immediate() { 00935 00936 interface->deinit(); 00937 interface->connection_status_cb(connection_down_cb); 00938 00939 // Enable PIN checking (which will use the current PIN), change 00940 // the PIN to MBED_CONF_APP_ALT_PIN, then try connecting after powering on and 00941 // off the modem 00942 interface->set_sim_pin_check(true, true, MBED_CONF_APP_DEFAULT_PIN); 00943 interface->set_new_sim_pin(MBED_CONF_APP_ALT_PIN, true); 00944 interface->deinit(); 00945 TEST_ASSERT(interface->init(NULL)); 00946 TEST_ASSERT(interface->connect(MBED_CONF_APP_ALT_PIN, MBED_CONF_APP_APN, 00947 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00948 use_connection(interface); 00949 drop_connection(interface); 00950 00951 interface->connection_status_cb(connection_down_cb); 00952 00953 // Now change the PIN back to what it was before 00954 interface->set_new_sim_pin(MBED_CONF_APP_DEFAULT_PIN, true); 00955 interface->deinit(); 00956 interface->set_sim_pin(MBED_CONF_APP_DEFAULT_PIN); 00957 TEST_ASSERT(interface->init(NULL)); 00958 TEST_ASSERT(interface->connect(NULL, MBED_CONF_APP_APN, MBED_CONF_APP_USERNAME, 00959 MBED_CONF_APP_PASSWORD) == 0); 00960 use_connection(interface); 00961 drop_connection(interface); 00962 00963 interface->connection_status_cb(connection_down_cb); 00964 00965 // Remove PIN checking again and check that it no 00966 // longer matters what the PIN is 00967 interface->set_sim_pin_check(false, true); 00968 interface->deinit(); 00969 TEST_ASSERT(interface->init(MBED_CONF_APP_INCORRECT_PIN)); 00970 TEST_ASSERT(interface->connect(NULL, MBED_CONF_APP_APN, MBED_CONF_APP_USERNAME, 00971 MBED_CONF_APP_PASSWORD) == 0); 00972 use_connection(interface); 00973 drop_connection(interface); 00974 00975 // Put the SIM pin back to the correct value for any subsequent tests 00976 interface->set_sim_pin(MBED_CONF_APP_DEFAULT_PIN); 00977 } 00978 00979 // Test being able to connect with a local instance of the interface 00980 // NOTE: since this local instance will fiddle with bits of HW that the 00981 // static instance thought it owned, the static instance will no longer 00982 // work afterwards, hence this must be run as the last test in the list 00983 void test_connect_local_instance_last_test() { 00984 00985 UbloxATCellularInterface *pLocalInterface = NULL; 00986 00987 pLocalInterface = new UbloxATCellularInterface(MDMTXD, MDMRXD, 00988 MBED_CONF_UBLOX_CELL_BAUD_RATE, 00989 MBED_CONF_APP_DEBUG_ON); 00990 pLocalInterface->connection_status_cb(connection_down_cb); 00991 00992 TEST_ASSERT(pLocalInterface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 00993 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00994 use_connection(pLocalInterface); 00995 drop_connection(pLocalInterface); 00996 delete pLocalInterface; 00997 00998 pLocalInterface = new UbloxATCellularInterface(MDMTXD, MDMRXD, 00999 MBED_CONF_UBLOX_CELL_BAUD_RATE, 01000 MBED_CONF_APP_DEBUG_ON); 01001 pLocalInterface->connection_status_cb(connection_down_cb); 01002 01003 TEST_ASSERT(pLocalInterface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 01004 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 01005 use_connection(pLocalInterface); 01006 drop_connection(pLocalInterface); 01007 delete pLocalInterface; 01008 } 01009 01010 // ---------------------------------------------------------------- 01011 // TEST ENVIRONMENT 01012 // ---------------------------------------------------------------- 01013 01014 // Setup the test environment 01015 utest::v1::status_t test_setup(const size_t number_of_cases) { 01016 // Setup Greentea with a timeout 01017 GREENTEA_SETUP(960, "default_auto"); 01018 return verbose_test_setup_handler(number_of_cases); 01019 } 01020 01021 // IMPORTANT!!! if you make a change to the tests here you should 01022 // check whether the same change should be made to the tests under 01023 // the PPP interface. 01024 01025 // Test cases 01026 Case cases[] = { 01027 Case("Set randomise", test_set_randomise), 01028 #ifdef MBED_CONF_APP_ECHO_SERVER 01029 Case("UDP echo test", test_udp_echo), 01030 # ifndef TARGET_UBLOX_C027 // Not enough RAM on little 'ole C027 to run this test 01031 Case("UDP recv sizes", test_udp_echo_recv_sizes), 01032 # endif 01033 Case("UDP async echo test", test_udp_echo_async), 01034 # ifndef TARGET_UBLOX_C027 // Not enough RAM on little 'ole C027 to run this test 01035 Case("TCP recv sizes", test_tcp_echo_recv_sizes), 01036 # endif 01037 Case("TCP async echo test", test_tcp_echo_async), 01038 #endif 01039 #ifndef TARGET_UBLOX_C027 // Not enough RAM on little 'ole C027 to run this test 01040 Case("Alloc max sockets", test_max_sockets), 01041 #endif 01042 Case("Connect with credentials", test_connect_credentials), 01043 Case("Connect with preset credentials", test_connect_preset_credentials), 01044 #if MBED_CONF_APP_RUN_SIM_PIN_CHANGE_TESTS 01045 Case("Check SIM pin, pending", test_check_sim_pin_pending), 01046 Case("Check SIM pin, immediate", test_check_sim_pin_immediate), 01047 #endif 01048 #ifndef TARGET_UBLOX_C027 // Not enough RAM on little 'ole C027 for this 01049 Case("Connect using local instance, must be last test", test_connect_local_instance_last_test) 01050 #endif 01051 }; 01052 01053 Specification specification(test_setup, cases); 01054 01055 // ---------------------------------------------------------------- 01056 // MAIN 01057 // ---------------------------------------------------------------- 01058 01059 int main() { 01060 01061 #ifdef FEATURE_COMMON_PAL 01062 mbed_trace_init(); 01063 01064 mbed_trace_mutex_wait_function_set(lock); 01065 mbed_trace_mutex_release_function_set(unlock); 01066 #endif 01067 01068 interface->connection_status_cb(connection_down_cb); 01069 01070 // Run tests 01071 return !Harness::run(specification); 01072 } 01073 01074 // End Of File 01075
Generated on Fri Jul 15 2022 01:47:11 by
1.7.2
