Wajahat Abbas / ublox-at-cellular-interface_tests
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     TEST_ASSERT(sleep_manager_can_deep_sleep() == true);
00225 
00226     // Create an instance of the cellular interface
00227     UbloxATCellularInterface *interface =
00228        new UbloxATCellularInterface(MDMTXD, MDMRXD,
00229                                     MBED_CONF_UBLOX_CELL_BAUD_RATE,
00230                                     MBED_CONF_APP_DEBUG_ON);
00231     interface->connection_status_cb(connection_down_cb);
00232 
00233     // Use it
00234 #ifdef TARGET_UBLOX_C030_R41XM
00235     int mno_profile;
00236     if (interface->init(MBED_CONF_APP_DEFAULT_PIN) == false) //init can return false if profile set is SW_DEFAULT
00237     {
00238         TEST_ASSERT(interface->get_mno_profile(&mno_profile));
00239         if (mno_profile == UbloxATCellularInterface::SW_DEFAULT) {
00240             TEST_ASSERT(interface->set_mno_profile((UbloxATCellularInterface::MNOProfile)MBED_CONF_UBLOX_CELL_DEFAULT_MNO_PROFILE));
00241             TEST_ASSERT(interface->reboot_modem());
00242             tr_debug("Reboot successful\n");
00243             wait_ms(5000);
00244         }
00245     }
00246     TEST_ASSERT(interface->init(MBED_CONF_APP_DEFAULT_PIN));
00247 
00248     TEST_ASSERT(interface->disable_psm());
00249 #else
00250     TEST_ASSERT(interface->init(MBED_CONF_APP_DEFAULT_PIN));
00251 #endif
00252     TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN,
00253                                    MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0);
00254     use_connection(interface);
00255     TEST_ASSERT(sleep_manager_can_deep_sleep() == false);
00256     drop_connection(interface);
00257     
00258     // Destroy the instance
00259     delete interface;
00260 
00261     TEST_ASSERT(sleep_manager_can_deep_sleep() == true);
00262 }
00263 
00264 // Test that if communication with the modem
00265 // fails for some reason that sleeping is possible
00266 // afterwards (specific case found by Rostyslav Y.)
00267 void test_sleep_failed_connection() {
00268     
00269     TEST_ASSERT(sleep_manager_can_deep_sleep() == true);
00270 
00271     // Create a bad instance of the cellular interface
00272     UbloxATCellularInterface *interface =
00273        new UbloxATCellularInterface(MDMTXD, MDMRXD,
00274                                     20, /* Silly baud rate */
00275                                     MBED_CONF_APP_DEBUG_ON);
00276 
00277     // [Fail to] use it
00278     TEST_ASSERT_FALSE(interface->init(MBED_CONF_APP_DEFAULT_PIN));
00279     TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN,
00280                                    MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) != NSAPI_ERROR_OK);
00281     // Destroy the instance
00282     delete interface;
00283 
00284     TEST_ASSERT(sleep_manager_can_deep_sleep() == true);
00285 }
00286 
00287 #if MBED_HEAP_STATS_ENABLED
00288 // Test for memory leaks.
00289 void test_memory_leak() {
00290     
00291     mbed_stats_heap_t heap_stats_start;
00292     mbed_stats_heap_t heap_stats;
00293 
00294     mbed_stats_heap_get(&heap_stats_start);
00295 
00296     // Create an instance of the cellular interface
00297     UbloxATCellularInterface *interface =
00298        new UbloxATCellularInterface(MDMTXD, MDMRXD,
00299                                     MBED_CONF_UBLOX_CELL_BAUD_RATE,
00300                                     MBED_CONF_APP_DEBUG_ON);
00301     interface->connection_status_cb(connection_down_cb);
00302 
00303     // Use it
00304     TEST_ASSERT(interface->init(MBED_CONF_APP_DEFAULT_PIN));
00305     TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN,
00306                                    MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0);
00307     mbed_stats_heap_get(&heap_stats);
00308     TEST_ASSERT(heap_stats.current_size > heap_stats_start.current_size);
00309     use_connection(interface);
00310     drop_connection(interface);
00311     
00312     // Destroy the instance
00313     delete interface;
00314 
00315     mbed_stats_heap_get(&heap_stats);
00316     TEST_ASSERT(heap_stats.current_size == heap_stats_start.current_size);
00317 }
00318 #endif
00319 
00320 // ----------------------------------------------------------------
00321 // TEST ENVIRONMENT
00322 // ----------------------------------------------------------------
00323 
00324 // Setup the test environment
00325 utest::v1::status_t test_setup(const size_t number_of_cases) {
00326     // Setup Greentea with a timeout
00327     GREENTEA_SETUP(300, "default_auto");
00328     return verbose_test_setup_handler(number_of_cases);
00329 }
00330 
00331 // IMPORTANT!!! if you make a change to the tests here you should
00332 // check whether the same change should be made to the tests under
00333 // the PPP interface.
00334 
00335 // Test cases
00336 Case cases[] = {
00337     Case("Sleep test", test_sleep),
00338     Case("Sleep test with failed modem comms", test_sleep_failed_connection)
00339 #if MBED_HEAP_STATS_ENABLED
00340     , Case("Memory leak test", test_memory_leak)
00341 #endif
00342 };
00343 
00344 Specification specification(test_setup, cases);
00345 
00346 // ----------------------------------------------------------------
00347 // MAIN
00348 // ----------------------------------------------------------------
00349 
00350 int main() {
00351 
00352 #ifdef FEATURE_COMMON_PAL
00353     mbed_trace_init();
00354 
00355     mbed_trace_mutex_wait_function_set(lock);
00356     mbed_trace_mutex_release_function_set(unlock);
00357 #endif
00358 
00359     // Run tests
00360     return !Harness::run(specification);
00361 }
00362 
00363 // End Of File