fork

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 #include "mbed_stats.h"
00007 #ifdef FEATURE_COMMON_PAL
00008 #include "mbed_trace.h"
00009 #define TRACE_GROUP "TEST"
00010 #else
00011 #define tr_debug(format, ...) debug(format "\n", ## __VA_ARGS__)
00012 #define tr_info(format, ...)  debug(format "\n", ## __VA_ARGS__)
00013 #define tr_warn(format, ...)  debug(format "\n", ## __VA_ARGS__)
00014 #define tr_error(format, ...) debug(format "\n", ## __VA_ARGS__)
00015 #endif
00016 
00017 using namespace utest::v1;
00018 
00019 // IMPORTANT!!! if you make a change to the tests here you should
00020 // check whether the same change should be made to the tests under
00021 // the PPP interface.
00022 
00023 // NOTE: these test are only as reliable as UDP across the internet
00024 // over a radio link.  The tests expect an NTP server to respond
00025 // to UDP packets and, if configured, an echo server to respond
00026 // to UDP packets.  This simply may not happen.  Please be patient.
00027 
00028 // ----------------------------------------------------------------
00029 // COMPILE-TIME MACROS
00030 // ----------------------------------------------------------------
00031 
00032 // These macros can be overridden with an mbed_app.json file and
00033 // contents of the following form:
00034 //
00035 //{
00036 //    "config": {
00037 //        "default-pin": {
00038 //            "value": "\"1234\""
00039 //        }
00040 //}
00041 //
00042 // See the template_mbed_app.txt in this directory for a fuller example.
00043 
00044 // Whether we can do the mbed stats tests or not
00045 #ifndef MBED_HEAP_STATS_ENABLED
00046 # define MBED_HEAP_STATS_ENABLED 0
00047 #endif
00048 
00049 // Whether debug trace is on
00050 #ifndef MBED_CONF_APP_DEBUG_ON
00051 # define MBED_CONF_APP_DEBUG_ON false
00052 #endif
00053 
00054 // The credentials of the SIM in the board.
00055 #ifndef MBED_CONF_APP_DEFAULT_PIN
00056 // Note: if PIN is enabled on your SIM, or you wish to run the SIM PIN change
00057 // tests, you must define the PIN for your SIM (see note above on using
00058 // mbed_app.json to do so).
00059 # define MBED_CONF_APP_DEFAULT_PIN "0000"
00060 #endif
00061 #ifndef MBED_CONF_APP_APN
00062 # define MBED_CONF_APP_APN         NULL
00063 #endif
00064 #ifndef MBED_CONF_APP_USERNAME
00065 # define MBED_CONF_APP_USERNAME    NULL
00066 #endif
00067 #ifndef MBED_CONF_APP_PASSWORD
00068 # define MBED_CONF_APP_PASSWORD    NULL
00069 #endif
00070 
00071 // Servers and ports
00072 #ifndef MBED_CONF_APP_NTP_SERVER
00073 # define MBED_CONF_APP_NTP_SERVER "2.pool.ntp.org"
00074 #else
00075 # ifndef MBED_CONF_APP_NTP_PORT
00076 #  error "MBED_CONF_APP_NTP_PORT must be defined if MBED_CONF_APP_NTP_SERVER is defined"
00077 # endif
00078 #endif
00079 #ifndef MBED_CONF_APP_NTP_PORT
00080 # define MBED_CONF_APP_NTP_PORT 123
00081 #endif
00082 
00083 // UDP packet size limit for testing
00084 #ifndef MBED_CONF_APP_UDP_MAX_PACKET_SIZE
00085 #  define MBED_CONF_APP_UDP_MAX_PACKET_SIZE 1024
00086 #endif
00087 
00088 // The number of retries for UDP exchanges
00089 #define NUM_UDP_RETRIES 5
00090 
00091 // ----------------------------------------------------------------
00092 // PRIVATE VARIABLES
00093 // ----------------------------------------------------------------
00094 
00095 #ifdef FEATURE_COMMON_PAL
00096 // Lock for debug prints
00097 static Mutex mtx;
00098 #endif
00099 
00100 // Connection flag
00101 static bool connection_has_gone_down = false;
00102 
00103 // ----------------------------------------------------------------
00104 // PRIVATE FUNCTIONS
00105 // ----------------------------------------------------------------
00106 
00107 #ifdef FEATURE_COMMON_PAL
00108 // Locks for debug prints
00109 static void lock()
00110 {
00111     mtx.lock();
00112 }
00113 
00114 static void unlock()
00115 {
00116     mtx.unlock();
00117 }
00118 #endif
00119 
00120 // Callback in case the connection goes down
00121 static void connection_down_cb(nsapi_error_t err)
00122 {
00123     connection_has_gone_down = true;
00124 }
00125 
00126 // Get NTP time from a socket
00127 static void do_ntp_sock (UDPSocket *sock, SocketAddress ntp_address)
00128 {
00129     char ntp_values[48] = { 0 };
00130     time_t timestamp = 0;
00131     int len;
00132     bool comms_done = false;
00133 
00134     ntp_values[0] = '\x1b';
00135 
00136     // Retry this a few times, don't want to fail due to a flaky link
00137     for (unsigned int x = 0; !comms_done && (x < NUM_UDP_RETRIES); x++) {
00138         sock->sendto(ntp_address, (void*) ntp_values, sizeof(ntp_values));
00139         len = sock->recvfrom(&ntp_address, (void*) ntp_values, sizeof(ntp_values));
00140         if (len > 0) {
00141             comms_done = true;
00142         }
00143     }
00144     TEST_ASSERT (comms_done);
00145 
00146     tr_debug("UDP: %d byte(s) returned by NTP server.", len);
00147     if (len >= 43) {
00148         struct tm *localTime;
00149         time_t TIME1970 = 2208988800U;
00150         timestamp |= ((int) *(ntp_values + 40)) << 24;
00151         timestamp |= ((int) *(ntp_values + 41)) << 16;
00152         timestamp |= ((int) *(ntp_values + 42)) << 8;
00153         timestamp |= ((int) *(ntp_values + 43));
00154         timestamp -= TIME1970;
00155         srand (timestamp);
00156         tr_debug("srand() called");
00157         localTime = localtime(&timestamp);
00158         if (localTime) {
00159             char timeString[25];
00160             if (strftime(timeString, sizeof(timeString), "%a %b %d %H:%M:%S %Y", localTime) > 0) {
00161                 printf("NTP timestamp is %s.\n", timeString);
00162             }
00163         }
00164     }
00165 }
00166 
00167 // Get NTP time
00168 static void do_ntp(UbloxATCellularInterface *interface)
00169 {
00170     UDPSocket sock;
00171     SocketAddress host_address;
00172 
00173     TEST_ASSERT(sock.open(interface) == 0)
00174 
00175     TEST_ASSERT(interface->gethostbyname(MBED_CONF_APP_NTP_SERVER, &host_address) == 0);
00176     host_address.set_port(MBED_CONF_APP_NTP_PORT);
00177 
00178     tr_debug("UDP: NIST server %s address: %s on port %d.", MBED_CONF_APP_NTP_SERVER,
00179              host_address.get_ip_address(), host_address.get_port());
00180 
00181     sock.set_timeout(10000);
00182 
00183     do_ntp_sock(&sock, host_address);
00184 
00185     sock.close();
00186 }
00187 
00188 // Use a connection, checking that it is good
00189 static void use_connection(UbloxATCellularInterface *interface)
00190 {
00191     const char * ip_address = interface->get_ip_address();
00192     const char * net_mask = interface->get_netmask();
00193     const char * gateway = interface->get_gateway();
00194 
00195     TEST_ASSERT(interface->is_connected());
00196 
00197     TEST_ASSERT(ip_address != NULL);
00198     tr_debug ("IP address %s.", ip_address);
00199     TEST_ASSERT(net_mask == NULL);
00200     tr_debug ("Net mask %s.", net_mask);
00201     TEST_ASSERT(gateway != NULL);
00202     tr_debug ("Gateway %s.", gateway);
00203 
00204     do_ntp(interface);
00205     TEST_ASSERT(!connection_has_gone_down);
00206 }
00207 
00208 // Drop a connection and check that it has dropped
00209 static void drop_connection(UbloxATCellularInterface *interface)
00210 {
00211     TEST_ASSERT(interface->disconnect() == 0);
00212     TEST_ASSERT(connection_has_gone_down);
00213     connection_has_gone_down = false;
00214     TEST_ASSERT(!interface->is_connected());
00215 }
00216 
00217 // ----------------------------------------------------------------
00218 // TESTS
00219 // ----------------------------------------------------------------
00220 
00221 // Test that sleep is possible both
00222 // before and after running the driver.
00223 void test_sleep() {
00224     
00225     TEST_ASSERT(sleep_manager_can_deep_sleep() == true);
00226 
00227     // Create an instance of the cellular interface
00228     UbloxATCellularInterface *interface =
00229        new UbloxATCellularInterface(MDMTXD, MDMRXD,
00230                                     MBED_CONF_UBLOX_CELL_BAUD_RATE,
00231                                     MBED_CONF_APP_DEBUG_ON);
00232     interface->connection_status_cb(connection_down_cb);
00233 
00234     // Use it
00235     TEST_ASSERT(interface->init(MBED_CONF_APP_DEFAULT_PIN));
00236     TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN,
00237                                    MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0);
00238     use_connection(interface);
00239     TEST_ASSERT(sleep_manager_can_deep_sleep() == false);
00240     drop_connection(interface);
00241     
00242     // Destroy the instance
00243     delete interface;
00244 
00245     TEST_ASSERT(sleep_manager_can_deep_sleep() == true);
00246 }
00247 
00248 // Test that if communication with the modem
00249 // fails for some reason that sleeping is possible
00250 // afterwards (specific case found by Rostyslav Y.)
00251 void test_sleep_failed_connection() {
00252     
00253     TEST_ASSERT(sleep_manager_can_deep_sleep() == true);
00254 
00255     // Create a bad instance of the cellular interface
00256     UbloxATCellularInterface *interface =
00257        new UbloxATCellularInterface(MDMTXD, MDMRXD,
00258                                     20, /* Silly baud rate */
00259                                     MBED_CONF_APP_DEBUG_ON);
00260 
00261     // [Fail to] use it
00262     TEST_ASSERT_FALSE(interface->init(MBED_CONF_APP_DEFAULT_PIN));
00263     TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN,
00264                                    MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) != NSAPI_ERROR_OK);
00265     // Destroy the instance
00266     delete interface;
00267 
00268     TEST_ASSERT(sleep_manager_can_deep_sleep() == true);
00269 }
00270 
00271 #if MBED_HEAP_STATS_ENABLED
00272 // Test for memory leaks.
00273 void test_memory_leak() {
00274     
00275     mbed_stats_heap_t heap_stats_start;
00276     mbed_stats_heap_t heap_stats;
00277 
00278     mbed_stats_heap_get(&heap_stats_start);
00279 
00280     // Create an instance of the cellular interface
00281     UbloxATCellularInterface *interface =
00282        new UbloxATCellularInterface(MDMTXD, MDMRXD,
00283                                     MBED_CONF_UBLOX_CELL_BAUD_RATE,
00284                                     MBED_CONF_APP_DEBUG_ON);
00285     interface->connection_status_cb(connection_down_cb);
00286 
00287     // Use it
00288     TEST_ASSERT(interface->init(MBED_CONF_APP_DEFAULT_PIN));
00289     TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN,
00290                                    MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0);
00291     mbed_stats_heap_get(&heap_stats);
00292     TEST_ASSERT(heap_stats.current_size > heap_stats_start.current_size);
00293     use_connection(interface);
00294     drop_connection(interface);
00295     
00296     // Destroy the instance
00297     delete interface;
00298 
00299     mbed_stats_heap_get(&heap_stats);
00300     TEST_ASSERT(heap_stats.current_size == heap_stats_start.current_size);
00301 }
00302 #endif
00303 
00304 // ----------------------------------------------------------------
00305 // TEST ENVIRONMENT
00306 // ----------------------------------------------------------------
00307 
00308 // Setup the test environment
00309 utest::v1::status_t test_setup(const size_t number_of_cases) {
00310     // Setup Greentea with a timeout
00311     GREENTEA_SETUP(300, "default_auto");
00312     return verbose_test_setup_handler(number_of_cases);
00313 }
00314 
00315 // IMPORTANT!!! if you make a change to the tests here you should
00316 // check whether the same change should be made to the tests under
00317 // the PPP interface.
00318 
00319 // Test cases
00320 Case cases[] = {
00321     Case("Sleep test", test_sleep),
00322     Case("Sleep test with failed modem comms", test_sleep_failed_connection)
00323 #if MBED_HEAP_STATS_ENABLED
00324     , Case("Memory leak test", test_memory_leak)
00325 #endif
00326 };
00327 
00328 Specification specification(test_setup, cases);
00329 
00330 // ----------------------------------------------------------------
00331 // MAIN
00332 // ----------------------------------------------------------------
00333 
00334 int main() {
00335 
00336 #ifdef FEATURE_COMMON_PAL
00337     mbed_trace_init();
00338 
00339     mbed_trace_mutex_wait_function_set(lock);
00340     mbed_trace_mutex_release_function_set(unlock);
00341 #endif
00342 
00343     // Run tests
00344     return !Harness::run(specification);
00345 }
00346 
00347 // End Of File