1 /*
2  * Copyright 2023 Meta
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/device.h>
9 #include <zephyr/drivers/rtc.h>
10 
11 #include <time.h>
12 
13 /* date "+%s" -d "Sat Jan  1 2000 00:00:00 GMT+0000" */
14 #define Y2K_STAMP 946684800UL
15 
16 #define SECONDS_BEFORE 1
17 #define SECONDS_AFTER 1
18 
19 #define RTC_TEST_START_TIME (Y2K_STAMP - SECONDS_BEFORE)
20 #define RTC_TEST_STOP_TIME (Y2K_STAMP + SECONDS_AFTER)
21 
22 static const struct device *rtc = DEVICE_DT_GET(DT_ALIAS(rtc));
23 
ZTEST(rtc_api,test_y2k)24 ZTEST(rtc_api, test_y2k)
25 {
26 	enum test_time {
27 		Y99,
28 		Y2K,
29 	};
30 
31 	static struct rtc_time rtm[2] = {
32 		{.tm_isdst = -1, .tm_nsec = 0},
33 		{.tm_isdst = -1, .tm_nsec = 0},
34 	};
35 	struct tm *const tm[2] = {
36 		(struct tm *const)&rtm[0],
37 		(struct tm *const)&rtm[1],
38 	};
39 	const time_t t[] = {
40 		[Y99] = RTC_TEST_START_TIME,
41 		[Y2K] = RTC_TEST_STOP_TIME,
42 	};
43 
44 	/* Party like it's 1999 */
45 	zassert_not_null(gmtime_r(&t[Y99], tm[Y99]));
46 
47 	int ret = rtc_set_time(rtc, &rtm[Y99]);
48 
49 	if (ret == -EINVAL) {
50 		TC_PRINT("Rollover not supported\n");
51 		ztest_test_skip();
52 	} else {
53 		zassert_ok(ret, "RTC Set Time Failed");
54 	}
55 
56 	/* Living after midnight */
57 	k_sleep(K_SECONDS(SECONDS_BEFORE + SECONDS_AFTER));
58 	zassert_ok(rtc_get_time(rtc, &rtm[Y2K]));
59 
60 	/* It's the end of the world as we know it */
61 	zassert_equal(rtm[Y2K].tm_year + 1900, 2000, "wrong year: %d", rtm[Y2K].tm_year + 1900);
62 	zassert_equal(rtm[Y2K].tm_mon, 0, "wrong month: %d", rtm[Y2K].tm_mon);
63 	zassert_equal(rtm[Y2K].tm_mday, 1, "wrong day-of-month: %d", rtm[Y2K].tm_mday);
64 	zassert_true(rtm[Y2K].tm_yday == 0 || rtm[Y2K].tm_yday == -1, "wrong day-of-year: %d",
65 		     rtm[Y2K].tm_yday);
66 	zassert_true(rtm[Y2K].tm_wday == 6 || rtm[Y2K].tm_wday == -1, "wrong day-of-week: %d",
67 		     rtm[Y2K].tm_wday);
68 	zassert_equal(rtm[Y2K].tm_hour, 0, "wrong hour: %d", rtm[Y2K].tm_hour);
69 	zassert_equal(rtm[Y2K].tm_min, 0, "wrong minute: %d", rtm[Y2K].tm_min);
70 	zassert_equal(rtm[Y2K].tm_sec, SECONDS_AFTER, "wrong second: %d", rtm[Y2K].tm_sec);
71 }
72