From f1ec6990593a8db655746f415619e1da7093a168 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Thu, 14 Jan 2016 07:28:21 -0800 Subject: [PATCH] Add time rtc ioctl tests - test read validity - test year setting from 1970 to 2037 (2015+ critical) - test year rollover operation (68 seconds to run test) Bug: 26346842 Change-Id: I225ca2a25c291b9d05d75f5f39de2c6c753fcba1 --- tests/timetest/Android.mk | 23 +++++++ tests/timetest/rtc_test.cpp | 149 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 tests/timetest/rtc_test.cpp diff --git a/tests/timetest/Android.mk b/tests/timetest/Android.mk index 05e21fbe..b2a1aa5b 100644 --- a/tests/timetest/Android.mk +++ b/tests/timetest/Android.mk @@ -1,6 +1,7 @@ # Copyright 2006 The Android Open Source Project LOCAL_PATH:= $(call my-dir) + include $(CLEAR_VARS) LOCAL_SRC_FILES:= timetest.c @@ -17,3 +18,25 @@ LOCAL_STATIC_LIBRARIES := libc include $(BUILD_EXECUTABLE) +# ----------------------------------------------------------------------------- +# Unit tests. +# ----------------------------------------------------------------------------- + +test_c_flags := \ + -fstack-protector-all \ + -g \ + -Wall -Wextra \ + -Werror \ + -fno-builtin \ + -std=gnu++11 + +test_src_files := \ + rtc_test.cpp + +include $(CLEAR_VARS) +LOCAL_MODULE := time-unit-tests +LOCAL_MODULE_TAGS := tests +LOCAL_CFLAGS += $(test_c_flags) +LOCAL_SRC_FILES := $(test_src_files) +include $(BUILD_NATIVE_TEST) + diff --git a/tests/timetest/rtc_test.cpp b/tests/timetest/rtc_test.cpp new file mode 100644 index 00000000..9dd6fd89 --- /dev/null +++ b/tests/timetest/rtc_test.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include + +static int hwtime(int flag, int request, struct rtc_time *tm) { + int ret; + do { + ret = TEMP_FAILURE_RETRY(open("/dev/rtc0", flag)); + if (ret < 0) { + ret = -errno; + } + } while (ret == -EBUSY); + if (ret < 0) { + return ret; + } + + int fd = ret; + do { + ret = TEMP_FAILURE_RETRY(ioctl(fd, request, tm)); + if (ret < 0) { + ret = -errno; + } + } while (ret == -EBUSY); + close(fd); + return ret; +} + +static int rd_hwtime(struct rtc_time *tm) { + return hwtime(O_RDONLY, RTC_RD_TIME, tm); +} + +static int set_hwtime(struct rtc_time *tm) { + return hwtime(O_WRONLY, RTC_SET_TIME, tm); +} + +TEST(time, rtc_rollover) { + struct rtc_time roll; + memset(&roll, 0, sizeof(roll)); + ASSERT_LE(0, rd_hwtime(&roll)); + int mday[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + mday[1] = (roll.tm_year % 4) ? 28 : 29; + ASSERT_LE(0, roll.tm_sec); + ASSERT_GT(60, roll.tm_sec); + ASSERT_LE(0, roll.tm_min); + ASSERT_GT(60, roll.tm_min); + ASSERT_LE(0, roll.tm_hour); + ASSERT_GT(24, roll.tm_hour); + ASSERT_LE(0, roll.tm_mday); + ASSERT_GE(mday[roll.tm_mon], roll.tm_mday); + ASSERT_LE(0, roll.tm_mon); + ASSERT_GT(12, roll.tm_mon); + ASSERT_LE(0, roll.tm_year); + ASSERT_GT(138, roll.tm_year); + + // Wait for granular clock + struct rtc_time save = roll; + static const useconds_t timeout_sleep = 10000; + static const int timeout_num = 2000000 / timeout_sleep; + int timeout; + for (timeout = timeout_num; timeout && (roll.tm_year == save.tm_year); --timeout) { + ASSERT_LE(0, rd_hwtime(&save)); + usleep(timeout_sleep); + } + + memset(&roll, 0, sizeof(roll)); + roll.tm_sec = 59; + roll.tm_min = 59; + roll.tm_hour = 23; + roll.tm_mday = 31; + roll.tm_mon = 11; + roll.tm_year = 70; + roll.tm_wday = 0; + roll.tm_yday = 0; + roll.tm_isdst = 0; + + for (roll.tm_year = 70; roll.tm_year < 137; ++roll.tm_year) { + struct rtc_time tm = roll; + int __set_hwtime = set_hwtime(&tm); + // below 2015, permitted to error out. + if ((__set_hwtime == -EINVAL) && (roll.tm_year < 115)) { + continue; + } + ASSERT_LE(0, __set_hwtime); + ASSERT_LE(0, rd_hwtime(&tm)); + ASSERT_EQ(roll.tm_sec, tm.tm_sec); + ASSERT_EQ(roll.tm_min, tm.tm_min); + ASSERT_EQ(roll.tm_hour, tm.tm_hour); + ASSERT_EQ(roll.tm_mday, tm.tm_mday); + ASSERT_EQ(roll.tm_mon, tm.tm_mon); + ASSERT_EQ(roll.tm_year, tm.tm_year); + for (timeout = timeout_num; timeout && (roll.tm_year == tm.tm_year); --timeout) { + ASSERT_LE(0, rd_hwtime(&tm)); + usleep(timeout_sleep); + } + ASSERT_EQ(roll.tm_year + 1, tm.tm_year); + EXPECT_LT(timeout_num * 5 / 100, timeout); + EXPECT_GT(timeout_num * 95 / 100, timeout); + + // correct saved time to compensate for rollover check + if (++save.tm_sec >= 60) { + save.tm_sec = 0; + if (++save.tm_min >= 60) { + save.tm_min = 0; + if (++save.tm_hour >= 24) { + save.tm_hour = 0; + mday[1] = (save.tm_year % 4) ? 28 : 29; + if (++save.tm_mday >= mday[save.tm_mon]) { + save.tm_mday = 1; + if (++save.tm_mon >= 12) { + save.tm_mon = 0; + ++save.tm_year; + } + } + } + } + } + } + + ASSERT_LE(0, set_hwtime(&save)); + ASSERT_LE(0, rd_hwtime(&roll)); + + ASSERT_EQ(save.tm_sec, roll.tm_sec); + ASSERT_EQ(save.tm_min, roll.tm_min); + ASSERT_EQ(save.tm_hour, roll.tm_hour); + ASSERT_EQ(save.tm_mday, roll.tm_mday); + ASSERT_EQ(save.tm_mon, roll.tm_mon); + ASSERT_EQ(save.tm_year, roll.tm_year); +} -- 2.11.0