rtc-test.c
1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #include <inttypes.h> 4 #include <rtc.h> 5 #include <string.h> 6 #include <tests/test.h> 7 8 static void test_rtc_to_tm_from_unix_time(void **state) 9 { 10 struct rtc_time tm; 11 int tim; 12 13 /* Zero-day */ 14 tim = 0; 15 assert_int_equal(0, rtc_to_tm(tim, &tm)); 16 assert_int_equal(1970, tm.year); 17 assert_int_equal(1, tm.mon); 18 assert_int_equal(1, tm.mday); 19 assert_int_equal(0, tm.hour); 20 assert_int_equal(0, tm.min); 21 assert_int_equal(0, tm.sec); 22 assert_int_equal(4, tm.wday); /* Thursday */ 23 24 /* One second from time base */ 25 tim = 1; 26 assert_int_equal(0, rtc_to_tm(tim, &tm)); 27 assert_int_equal(1970, tm.year); 28 assert_int_equal(1, tm.mon); 29 assert_int_equal(1, tm.mday); 30 assert_int_equal(0, tm.hour); 31 assert_int_equal(0, tm.min); 32 assert_int_equal(1, tm.sec); 33 assert_int_equal(4, tm.wday); /* Thursday */ 34 35 /* Full time value */ 36 tim = INT32_MAX; 37 assert_int_equal(0, rtc_to_tm(tim, &tm)); 38 assert_int_equal(2038, tm.year); 39 assert_int_equal(1, tm.mon); 40 assert_int_equal(19, tm.mday); 41 assert_int_equal(3, tm.hour); 42 assert_int_equal(14, tm.min); 43 assert_int_equal(7, tm.sec); 44 assert_int_equal(2, tm.wday); /* Tuesday */ 45 46 /* Other common value */ 47 tim = 1618484725; 48 assert_int_equal(0, rtc_to_tm(tim, &tm)); 49 assert_int_equal(2021, tm.year); 50 assert_int_equal(4, tm.mon); 51 assert_int_equal(15, tm.mday); 52 assert_int_equal(11, tm.hour); 53 assert_int_equal(5, tm.min); 54 assert_int_equal(25, tm.sec); 55 assert_int_equal(4, tm.wday); /* Thursday */ 56 57 /* Negative value - expect incorrect output */ 58 tim = -1; 59 assert_int_equal(0, rtc_to_tm(tim, &tm)); 60 assert_int_equal(1970, tm.year); 61 assert_int_equal(1, tm.mon); 62 assert_int_equal(1, tm.mday); 63 assert_int_equal(0, tm.hour); 64 assert_int_equal(0, tm.min); 65 assert_int_equal(-1, tm.sec); 66 assert_int_equal(4, tm.wday); /* Thursday */ 67 } 68 69 static void test_mktime(void **state) 70 { 71 struct rtc_time tm; 72 struct rtc_time tm2; 73 memset(&tm, 0, sizeof(tm)); 74 memset(&tm2, 0, sizeof(tm2)); 75 76 /* Epoch start */ 77 tm = (struct rtc_time){ 78 .year = 1970, .mon = 1, .mday = 1, .hour = 0, .min = 0, .sec = 0, 79 }; 80 assert_int_equal(0, rtc_mktime(&tm)); 81 82 /* Last correct value */ 83 tm = (struct rtc_time){ 84 .year = 2038, .mon = 1, .mday = 19, .hour = 3, .min = 14, .sec = 7, 85 }; 86 assert_int_equal(INT32_MAX, rtc_mktime(&tm)); 87 88 /* Common non-leap year */ 89 tm = (struct rtc_time){ 90 .year = 1999, .mon = 12, .mday = 6, .hour = 16, .min = 13, .sec = 59, 91 }; 92 assert_int_equal(944496839, rtc_mktime(&tm)); 93 94 /* Ensure that February 29 gives the same result as March 1 in non-leap year */ 95 tm = (struct rtc_time){ 96 .year = 2017, .mon = 2, .mday = 29, .hour = 1, .min = 2, .sec = 3, 97 }; 98 tm2 = (struct rtc_time){ 99 .year = 2017, .mon = 3, .mday = 1, .hour = 1, .min = 2, .sec = 3, 100 }; 101 assert_int_equal(rtc_mktime(&tm), rtc_mktime(&tm2)); 102 103 /* Leap year (only division by 4 rule applies) */ 104 tm = (struct rtc_time){ 105 .year = 2004, .mon = 8, .mday = 30, .hour = 13, .min = 45, .sec = 33, 106 }; 107 assert_int_equal(1093873533, rtc_mktime(&tm)); 108 /* Last day of February in leap year */ 109 tm.mon = 2; 110 tm.mday = 29; 111 assert_int_equal(1078062333, rtc_mktime(&tm)); 112 /* Ensure that February 29 and March 1 have different and correct values 113 in leap year */ 114 tm = (struct rtc_time){ 115 .year = 2004, .mon = 3, .mday = 1, .hour = 7, .min = 7, .sec = 17, 116 }; 117 tm2 = (struct rtc_time){ 118 .year = 2004, .mon = 2, .mday = 29, .hour = 7, .min = 7, .sec = 17, 119 }; 120 /* There should be exactly one day of difference */ 121 assert_int_equal(24 * 60 * 60, rtc_mktime(&tm) - rtc_mktime(&tm2)); 122 123 /* Leap year (division by 400 rule applies and division by 100 is excluded) */ 124 tm = (struct rtc_time){ 125 .year = 2000, .mon = 6, .mday = 11, .hour = 21, .min = 3, .sec = 6, 126 }; 127 assert_int_equal(960757386, rtc_mktime(&tm)); 128 tm.mon = 2; 129 tm.mday = 29; 130 assert_int_equal(951858186, rtc_mktime(&tm)); 131 132 tm = (struct rtc_time){ 133 .year = 2000, .mon = 3, .mday = 1, .hour = 10, .min = 55, .sec = 21, 134 }; 135 tm2 = (struct rtc_time){ 136 .year = 2000, .mon = 2, .mday = 29, .hour = 10, .min = 55, .sec = 21, 137 }; 138 assert_int_equal(24 * 60 * 60, rtc_mktime(&tm) - rtc_mktime(&tm2)); 139 } 140 141 static void assert_rtc_time_equal(struct rtc_time *tm1, struct rtc_time *tm2) 142 { 143 assert_int_equal(tm1->sec, tm2->sec); 144 assert_int_equal(tm1->min, tm2->min); 145 assert_int_equal(tm1->hour, tm2->hour); 146 assert_int_equal(tm1->mday, tm2->mday); 147 assert_int_equal(tm1->mon, tm2->mon); 148 assert_int_equal(tm1->year, tm2->year); 149 assert_int_equal(tm1->wday, tm2->wday); 150 } 151 152 /* This test check if combination of rtc_to_tm and rtc_mktime gives result equal to input. 153 Week day is ignored by rtc_mktime, but is calculated by rtc_to_tm, so it is included 154 in input. */ 155 static void test_rtc_mktime_with_rtc_to_tm(void **state) 156 { 157 struct rtc_time tm_in; 158 struct rtc_time tm_out; 159 int tim; 160 161 memset(&tm_in, 0, sizeof(tm_in)); 162 memset(&tm_out, 0, sizeof(tm_out)); 163 164 /* Conversion from rtc_time to timestamp and back to rtc_time */ 165 tm_in = (struct rtc_time){ 166 .year = 1970, .mon = 1, .mday = 1, .hour = 0, .min = 0, .sec = 0, .wday = 4, 167 }; 168 assert_int_equal(0, rtc_to_tm(rtc_mktime(&tm_in), &tm_out)); 169 assert_rtc_time_equal(&tm_in, &tm_out); 170 171 tm_in = (struct rtc_time){ 172 .year = 2000, .mon = 2, .mday = 29, .hour = 13, .min = 4, .sec = 15, .wday = 2, 173 }; 174 assert_int_equal(0, rtc_to_tm(rtc_mktime(&tm_in), &tm_out)); 175 assert_rtc_time_equal(&tm_in, &tm_out); 176 177 tm_in = (struct rtc_time){ 178 .year = 2000, .mon = 3, .mday = 1, .hour = 13, .min = 8, .sec = 37, .wday = 3, 179 }; 180 assert_int_equal(0, rtc_to_tm(rtc_mktime(&tm_in), &tm_out)); 181 assert_rtc_time_equal(&tm_in, &tm_out); 182 183 tm_in = (struct rtc_time){ 184 .year = 2017, .mon = 12, .mday = 7, .hour = 8, .min = 18, .sec = 9, .wday = 4, 185 }; 186 assert_int_equal(0, rtc_to_tm(rtc_mktime(&tm_in), &tm_out)); 187 assert_rtc_time_equal(&tm_in, &tm_out); 188 189 tm_in = (struct rtc_time){ 190 .year = 2020, .mon = 2, .mday = 29, .hour = 18, .min = 50, .sec = 0, .wday = 6, 191 }; 192 assert_int_equal(0, rtc_to_tm(rtc_mktime(&tm_in), &tm_out)); 193 assert_rtc_time_equal(&tm_in, &tm_out); 194 195 tm_in = (struct rtc_time){ 196 .year = 2020, .mon = 3, .mday = 1, .hour = 1, .min = 20, .sec = 23, .wday = 0, 197 }; 198 assert_int_equal(0, rtc_to_tm(rtc_mktime(&tm_in), &tm_out)); 199 assert_rtc_time_equal(&tm_in, &tm_out); 200 201 202 /* Conversion from timestamp to rtc_time and back to timestamp */ 203 tim = 0; 204 rtc_to_tm(tim, &tm_out); 205 assert_int_equal(tim, rtc_mktime(&tm_out)); 206 207 tim = INT32_MAX; 208 rtc_to_tm(tim, &tm_out); 209 assert_int_equal(tim, rtc_mktime(&tm_out)); 210 211 /* 2000-02-29 1:23:34 */ 212 tim = 951787414; 213 rtc_to_tm(tim, &tm_out); 214 assert_int_equal(tim, rtc_mktime(&tm_out)); 215 216 /* 2000-03-01 1:23:34 */ 217 tim = 951873814; 218 rtc_to_tm(tim, &tm_out); 219 assert_int_equal(tim, rtc_mktime(&tm_out)); 220 221 /* 1999-09-09 9:09:09 */ 222 tim = 936868149; 223 rtc_to_tm(tim, &tm_out); 224 assert_int_equal(tim, rtc_mktime(&tm_out)); 225 226 /* 2020-02-29 2:29:02 */ 227 tim = 1582943342; 228 rtc_to_tm(tim, &tm_out); 229 assert_int_equal(tim, rtc_mktime(&tm_out)); 230 231 /* 2020-03-01 3:01:03 */ 232 tim = 1583031663; 233 rtc_to_tm(tim, &tm_out); 234 assert_int_equal(tim, rtc_mktime(&tm_out)); 235 } 236 237 static void test_leap_day_secday(void **state) 238 { 239 const int secday = 60 * 60 * 24; 240 struct rtc_time tm_in; 241 struct rtc_time tm_out; 242 struct rtc_time tm_expected; 243 int tim; 244 245 memset(&tm_in, 0, sizeof(tm_in)); 246 memset(&tm_out, 0, sizeof(tm_out)); 247 248 /* Non-leap year */ 249 tm_in = (struct rtc_time){ 250 .year = 1999, .mon = 2, .mday = 28, .hour = 5, .min = 37, .sec = 15, .wday = 0, 251 }; 252 tim = rtc_mktime(&tm_in) + secday; 253 tm_expected = (struct rtc_time){ 254 .year = 1999, .mon = 3, .mday = 1, .hour = 5, .min = 37, .sec = 15, .wday = 1, 255 }; 256 assert_int_equal(0, rtc_to_tm(tim, &tm_out)); 257 assert_rtc_time_equal(&tm_out, &tm_expected); 258 259 /* Leap-year February 28 to February 29 */ 260 tm_in = (struct rtc_time){ 261 .year = 2000, .mon = 2, .mday = 28, .hour = 0, .min = 33, .sec = 11, .wday = 1, 262 }; 263 tim = rtc_mktime(&tm_in) + secday; 264 tm_expected = (struct rtc_time){ 265 .year = 2000, .mon = 2, .mday = 29, .hour = 0, .min = 33, .sec = 11, .wday = 2, 266 }; 267 assert_int_equal(0, rtc_to_tm(tim, &tm_out)); 268 assert_rtc_time_equal(&tm_out, &tm_expected); 269 270 tm_in = (struct rtc_time){ 271 .year = 2004, .mon = 2, .mday = 28, .hour = 9, .min = 13, .sec = 45, .wday = 6, 272 }; 273 tim = rtc_mktime(&tm_in) + secday; 274 tm_expected = (struct rtc_time){ 275 .year = 2004, .mon = 2, .mday = 29, .hour = 9, .min = 13, .sec = 45, .wday = 0, 276 }; 277 assert_int_equal(0, rtc_to_tm(tim, &tm_out)); 278 assert_rtc_time_equal(&tm_out, &tm_expected); 279 280 /* Leap-year February 29 to March 1 */ 281 tm_in = (struct rtc_time){ 282 .year = 2000, .mon = 2, .mday = 29, .hour = 22, .min = 50, .sec = 25, .wday = 2, 283 }; 284 tim = rtc_mktime(&tm_in) + secday; 285 tm_expected = (struct rtc_time){ 286 .year = 2000, .mon = 3, .mday = 1, .hour = 22, .min = 50, .sec = 25, .wday = 3, 287 }; 288 assert_int_equal(0, rtc_to_tm(tim, &tm_out)); 289 assert_rtc_time_equal(&tm_out, &tm_expected); 290 291 tm_in = (struct rtc_time){ 292 .year = 2004, .mon = 2, .mday = 29, .hour = 17, .min = 56, .sec = 27, .wday = 0, 293 }; 294 tim = rtc_mktime(&tm_in) + secday; 295 tm_expected = (struct rtc_time){ 296 .year = 2004, .mon = 3, .mday = 1, .hour = 17, .min = 56, .sec = 27, .wday = 1, 297 }; 298 assert_int_equal(0, rtc_to_tm(tim, &tm_out)); 299 assert_rtc_time_equal(&tm_out, &tm_expected); 300 } 301 302 int main(void) 303 { 304 const struct CMUnitTest tests[] = { 305 cmocka_unit_test(test_rtc_to_tm_from_unix_time), 306 cmocka_unit_test(test_mktime), 307 cmocka_unit_test(test_rtc_mktime_with_rtc_to_tm), 308 cmocka_unit_test(test_leap_day_secday), 309 }; 310 311 return cb_run_group_tests(tests, NULL, NULL); 312 }