The test case rtc.date_read_loop in rtctest.c fails intermittently because
it checks that the RTC time does not advance by more than 1 second per loop
iteration. However, the loop sleeps for 11ms via nanosleep(), and if the
test thread is descheduled by the OS scheduler (e.g., under heavy system
load in a VM), more than 1 second can elapse between consecutive RTC reads.
This causes the next RTC time read to be 2 or more seconds ahead of the
previous read, triggering a test assertion failure.

To make the test more resilient against OS scheduling delays, measure the
real elapsed time between iterations using a monotonic clock
(clock_gettime(CLOCK_MONOTONIC)), and compute the actual number of seconds
elapsed (delta_s) between consecutive RTC reads. Then dynamically adjust
the assertion to:
ASSERT_GE(prev_rtc_read + delta_s + 1, rtc_read);

Signed-off-by: Wake Liu <[email protected]>
---
 tools/testing/selftests/rtc/rtctest.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/rtc/rtctest.c 
b/tools/testing/selftests/rtc/rtctest.c
index 8047d9879039..54eb5c255a45 100644
--- a/tools/testing/selftests/rtc/rtctest.c
+++ b/tools/testing/selftests/rtc/rtctest.c
@@ -116,6 +116,7 @@ TEST_F_TIMEOUT(rtc, date_read_loop, READ_LOOP_DURATION_SEC 
+ 2) {
        long iter_count = 0;
        struct rtc_time rtc_tm;
        time_t start_rtc_read, prev_rtc_read;
+       struct timespec prev_mono, cur_mono;
 
        if (self->fd == -1 && errno == ENOENT)
                SKIP(return, "Skipping test since %s does not exist", rtc_file);
@@ -126,25 +127,31 @@ TEST_F_TIMEOUT(rtc, date_read_loop, 
READ_LOOP_DURATION_SEC + 2) {
 
        rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm);
        ASSERT_NE(-1, rc);
+       clock_gettime(CLOCK_MONOTONIC, &prev_mono);
        start_rtc_read = rtc_time_to_timestamp(&rtc_tm);
        prev_rtc_read = start_rtc_read;
 
        do  {
                time_t rtc_read;
+               time_t delta_s = 0;
 
                rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm);
                ASSERT_NE(-1, rc);
+               clock_gettime(CLOCK_MONOTONIC, &cur_mono);
 
                rtc_read = rtc_time_to_timestamp(&rtc_tm);
+               delta_s = cur_mono.tv_sec - prev_mono.tv_sec;
+
                /* Time should not go backwards */
                ASSERT_LE(prev_rtc_read, rtc_read);
-               /* Time should not increase more then 1s at a time */
-               ASSERT_GE(prev_rtc_read + 1, rtc_read);
+               /* Time should not increase more then elapsed time + 1s */
+               ASSERT_GE(prev_rtc_read + delta_s + 1, rtc_read);
 
                /* Sleep 11ms to avoid killing / overheating the RTC */
                nanosleep_with_retries(READ_LOOP_SLEEP_MS * 1000000);
 
                prev_rtc_read = rtc_read;
+               prev_mono = cur_mono;
                iter_count++;
        } while (prev_rtc_read <= start_rtc_read + READ_LOOP_DURATION_SEC);
 
-- 
2.54.0.545.g6539524ca2-goog


Reply via email to