/ tests / lib / rtc-test.c
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  }