Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2017 ARM Limited
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 "utest/utest.h"
00018 #include "unity/unity.h"
00019 #include "greentea-client/test_env.h"
00020 
00021 #include "mbed.h"
00022 #include "mbed_mktime.h"
00023 
00024 // Limit the test range to 1935 for IAR only. From the IAR C/C++ Development Guide:
00025 // "The 32-bit interface supports years from 1900 up to 2035 and uses a 32-bit integer
00026 // for time_t."
00027 #ifdef __ICCARM__
00028 #define LOCALTIME_MAX       2082758400      // 1st of january 2036 at 00:00:00
00029 #define MKTIME_YR_MAX       136
00030 #else
00031 #define LOCALTIME_MAX       INT_MAX
00032 #define MKTIME_YR_MAX       137
00033 #endif
00034 
00035 using namespace utest::v1;
00036 
00037 /* 
00038  * regular is_leap_year, see platform/mbed_mktime.c for the optimized version
00039  */
00040 bool is_leap_year(int year) {
00041     year = 1900 + year;
00042     if (year % 4) {
00043         return false;
00044     } else if (year % 100) {
00045         return true;
00046     } else if (year % 400) {
00047         return false;
00048     }
00049     return true;
00050 }
00051 
00052 /*
00053  * Test the optimized version of _rtc_is_leap_year against the generic version.
00054  */
00055 void test_is_leap_year() { 
00056     for (int i = 70; i < 138; ++i) { 
00057         bool expected = is_leap_year(i);
00058         bool actual_value = _rtc_is_leap_year(i);
00059 
00060         if (expected != actual_value) { 
00061             printf ("leap year failed with i = %d\r\n", i);
00062         }
00063         TEST_ASSERT_EQUAL(expected, actual_value);
00064     }
00065 }
00066 
00067 struct tm make_time_info(int year, int month, int day, int hours, int minutes, int seconds) { 
00068     struct tm timeinfo = {
00069             seconds,    // tm_sec
00070             minutes,    // tm_min
00071             hours,      // tm_hour
00072             day,        // tm_mday
00073             month,      // tm_mon
00074             year,       // tm_year
00075             0,          // tm_wday
00076             0,          // tm_yday
00077             0,          // tm_isdst
00078     };
00079     return timeinfo;
00080 }
00081 
00082 /*
00083  * test out of range values for _rtc_mktime.
00084  * The function operates from the 1st of january 1970 at 00:00:00 to the 19th 
00085  * of january 2038 at 03:14:07.
00086  */
00087 void test_mk_time_out_of_range() { 
00088     tm invalid_lower_bound = make_time_info(
00089         69,
00090         11,
00091         31,
00092         23,
00093         59,
00094         59
00095     );    
00096 
00097     tm valid_lower_bound = make_time_info(
00098         70,
00099         0,
00100         1,
00101         0,
00102         0,
00103         0
00104     );
00105 
00106     tm valid_upper_bound = make_time_info(
00107         138,
00108         0,
00109         19,
00110         3,
00111         14,
00112         7
00113     );
00114 
00115     tm invalid_upper_bound = make_time_info(
00116         138,
00117         0,
00118         19,
00119         3,
00120         14,
00121         8
00122     );
00123 
00124     TEST_ASSERT_EQUAL_INT(((time_t) -1), _rtc_mktime(&invalid_lower_bound));
00125     TEST_ASSERT_EQUAL_INT(((time_t) 0), _rtc_mktime(&valid_lower_bound));
00126     TEST_ASSERT_EQUAL_INT(((time_t) INT_MAX), _rtc_mktime(&valid_upper_bound));
00127     TEST_ASSERT_EQUAL_INT(((time_t) -1), _rtc_mktime(&invalid_upper_bound));
00128 }
00129 
00130 /* 
00131  * test mktime over a large set of values 
00132  */
00133 void test_mk_time() { 
00134     for (size_t year = 70; year < MKTIME_YR_MAX; ++year) {
00135         for (size_t month = 0; month < 12; ++month) { 
00136             for (size_t day = 1; day < 32; ++day) {
00137                 if (month == 1 && is_leap_year(year) && day == 29) { 
00138                     break;
00139                 } else if(month == 1 && !is_leap_year(year) && day == 28) {
00140                     break;
00141                 } else if (
00142                     day == 31 && 
00143                     (month == 3 || month == 5 || month == 8 || month == 10)
00144                 ) {
00145                     break;
00146                 }
00147 
00148                 for (size_t hour = 0; hour < 24; ++hour) {  
00149                     tm time_info = make_time_info(
00150                         year,
00151                         month,
00152                         day,
00153                         hour,
00154                         hour % 2 ? 59 : 0,
00155                         hour % 2 ? 59 : 0
00156                     );
00157 
00158                     time_t expected = mktime(&time_info);
00159                     time_t actual_value = _rtc_mktime(&time_info);
00160 
00161                     char msg[128] = "";
00162                     if (expected != actual_value) { 
00163                         snprintf(
00164                             msg, sizeof(msg), 
00165                             "year = %d, month = %d, day = %d, diff = %ld", 
00166                             year, month, day, expected - actual_value
00167                         );
00168                     }
00169 
00170                     TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual_value, msg);
00171                 }
00172             }
00173         }
00174     }
00175 }
00176 
00177 /* 
00178  * test value out of range for localtime
00179  */
00180 void test_local_time_limit() {
00181     struct tm dummy_value; 
00182     TEST_ASSERT_FALSE(_rtc_localtime((time_t) -1, &dummy_value));
00183     TEST_ASSERT_FALSE(_rtc_localtime((time_t) INT_MIN, &dummy_value));
00184 }
00185 
00186 /* 
00187  * test _rtc_localtime over a large set of values.
00188  */
00189 void test_local_time() { 
00190     for (uint32_t i = 0; i < LOCALTIME_MAX; i += 3451) {
00191         time_t copy = (time_t) i;
00192         struct tm* expected = localtime(&copy);
00193         struct tm actual_value; 
00194         bool result = _rtc_localtime((time_t) i, &actual_value);
00195 
00196         if (
00197             expected->tm_sec != actual_value.tm_sec || 
00198             expected->tm_min != actual_value.tm_min ||
00199             expected->tm_hour != actual_value.tm_hour || 
00200             expected->tm_mday != actual_value.tm_mday ||
00201             expected->tm_mon != actual_value.tm_mon || 
00202             expected->tm_year != actual_value.tm_year || 
00203             expected->tm_wday != actual_value.tm_wday || 
00204             expected->tm_yday != actual_value.tm_yday ||
00205             result == false
00206         ) { 
00207             printf("error: i = %lu\r\n", i);
00208         }
00209 
00210         TEST_ASSERT_TRUE(result);
00211         TEST_ASSERT_EQUAL_UINT32_MESSAGE(
00212             expected->tm_sec, actual_value.tm_sec, "invalid seconds"
00213         );
00214         TEST_ASSERT_EQUAL_UINT32_MESSAGE(
00215             expected->tm_min, actual_value.tm_min, "invalid minutes"
00216         );
00217         TEST_ASSERT_EQUAL_UINT32_MESSAGE(
00218             expected->tm_hour, actual_value.tm_hour, "invalid hours"
00219         );
00220         TEST_ASSERT_EQUAL_UINT32_MESSAGE(
00221             expected->tm_mday, actual_value.tm_mday, "invalid day"
00222         );
00223         TEST_ASSERT_EQUAL_UINT32_MESSAGE(
00224             expected->tm_mon, actual_value.tm_mon, "invalid month"
00225         );
00226         TEST_ASSERT_EQUAL_UINT32_MESSAGE(
00227             expected->tm_year, actual_value.tm_year, "invalid year"
00228         );
00229         TEST_ASSERT_EQUAL_UINT32_MESSAGE(
00230             expected->tm_wday, actual_value.tm_wday, "invalid weekday"
00231         );
00232         TEST_ASSERT_EQUAL_UINT32_MESSAGE(
00233             expected->tm_yday, actual_value.tm_yday, "invalid year day"
00234         );
00235     }
00236 }
00237 
00238 utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) {
00239     greentea_case_failure_abort_handler(source, reason);
00240     return STATUS_CONTINUE;
00241 }
00242 
00243 Case cases[] = {
00244     Case("test is leap year", test_is_leap_year, greentea_failure_handler),
00245     Case("test mk time out of range values", test_mk_time_out_of_range, greentea_failure_handler),
00246     Case("mk time", test_mk_time, greentea_failure_handler),
00247     Case("test local time", test_local_time, greentea_failure_handler),
00248     Case("test local time limits", test_local_time_limit, greentea_failure_handler),
00249 };
00250 
00251 utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
00252     GREENTEA_SETUP(1200, "default_auto");
00253     return greentea_test_setup_handler(number_of_cases);
00254 }
00255 
00256 Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
00257 
00258 int main() {
00259     return Harness::run(specification);
00260 }