mirror of https://github.com/ARMmbed/mbed-os.git
141 lines
6.0 KiB
Python
141 lines
6.0 KiB
Python
"""
|
|
mbed SDK
|
|
Copyright (c) 2011-2013 ARM Limited
|
|
|
|
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.
|
|
"""
|
|
|
|
from mbed_host_tests import BaseHostTest
|
|
import time
|
|
import calendar
|
|
import datetime
|
|
|
|
class RTC_time_calc_test(BaseHostTest):
|
|
"""
|
|
This is the host part of the test to verify if:
|
|
- _rtc_mktime function converts a calendar time into time since UNIX epoch as a time_t,
|
|
- _rtc_localtime function converts a given time in seconds since epoch into calendar time.
|
|
|
|
The same algoritm to generate next calendar time to be tested is used by both parts of the test.
|
|
We will check if correct time since UNIX epoch is calculated for the first and the last day
|
|
of each month and across valid years.
|
|
|
|
Mbed part of the test sends calculated time since UNIX epoch.
|
|
This part validates given value and responds to indicate pass or fail.
|
|
Additionally it sends also encoded day of week and day of year which
|
|
will be needed to verify _rtc_localtime.
|
|
|
|
Support for both types of RTC devices is provided:
|
|
- RTCs which handles all leap years in the mentioned year range correctly. Leap year is determined by checking if
|
|
the year counter value is divisible by 400, 100, and 4. No problem here.
|
|
- RTCs which handles leap years correctly up to 2100. The RTC does a simple bit comparison to see if the two
|
|
lowest order bits of the year counter are zero. In this case 2100 year will be considered
|
|
incorrectly as a leap year, so the last valid point in time will be 28.02.2100 23:59:59 and next day will be
|
|
29.02.2100 (invalid). So after 28.02.2100 the day counter will be off by a day.
|
|
|
|
"""
|
|
|
|
edge_date = datetime.datetime(2100, 2, 28, 0, 0, 0)
|
|
|
|
# Test the following years:
|
|
# - first - 1970
|
|
# - example not leap year (not divisible by 4)
|
|
# - example leap year (divisible by 4 and by 100 and by 400)
|
|
# - example leap year (divisible by 4 and not by 100)
|
|
# - example not leap year (divisible by 4 and by 100)
|
|
# - last fully supported - 2105
|
|
years = [1970, 1971, 2000, 2096, 2100, 2105]
|
|
year_id = 0
|
|
|
|
|
|
|
|
full_leap_year_support = False
|
|
|
|
RTC_FULL_LEAP_YEAR_SUPPORT = 0
|
|
RTC_PARTIAL_LEAP_YEAR_SUPPORT = 1
|
|
|
|
def _set_leap_year_support(self, key, value, timestamp):
|
|
if (int(value) == self.RTC_FULL_LEAP_YEAR_SUPPORT):
|
|
self.full_leap_year_support = True
|
|
else:
|
|
self.full_leap_year_support = False
|
|
|
|
self.first = True
|
|
self.date = datetime.datetime(1970, 1, 1, 23, 0, 0)
|
|
self.year_id = 0
|
|
|
|
def _verify_timestamp(self, key, value, timestamp):
|
|
# week day in python is counted from sunday(0) and on mbed side week day is counted from monday(0).
|
|
# year day in python is counted from 1 and on mbed side year day is counted from 0.
|
|
week_day = ((self.date.timetuple().tm_wday + 1) % 7)
|
|
year_day = self.date.timetuple().tm_yday - 1
|
|
|
|
# Fix for RTC which not have full leap year support.
|
|
if (not self.full_leap_year_support):
|
|
if self.date >= self.edge_date:
|
|
# After 28.02.2100 we should be one day off - add this day and store original
|
|
date_org = self.date
|
|
self.date += datetime.timedelta(days = 1)
|
|
|
|
# Adjust week day.
|
|
week_day = ((self.date.timetuple().tm_wday + 1) % 7)
|
|
|
|
# Adjust year day.
|
|
if (self.date.year == 2100):
|
|
year_day = self.date.timetuple().tm_yday - 1
|
|
else:
|
|
year_day = date_org.timetuple().tm_yday - 1
|
|
|
|
# Last day in year
|
|
if (self.date.month == 1 and self.date.day == 1):
|
|
if (self.date.year == 2101):
|
|
# Exception for year 2100 - ivalid handled by RTC without full leap year support
|
|
year_day = 365
|
|
else:
|
|
year_day = date_org.timetuple().tm_yday - 1
|
|
|
|
t = (self.date.year , self.date.month, self.date.day, self.date.hour, self.date.minute, self.date.second, 0, 0, 0)
|
|
|
|
expected_timestamp = calendar.timegm(t)
|
|
actual_timestamp = int(value) & 0xffffffff # convert to unsigned int
|
|
|
|
# encode week day and year day in the response
|
|
response = (week_day << 16) | year_day
|
|
|
|
if (actual_timestamp == expected_timestamp):
|
|
# response contains encoded week day and year day
|
|
self.send_kv("passed", str(response))
|
|
else:
|
|
self.send_kv("failed", 0)
|
|
print "expected = %d, result = %d" % (expected_timestamp , actual_timestamp)
|
|
|
|
# calculate next date
|
|
if (self.first):
|
|
days_range = calendar.monthrange(self.date.year, self.date.month)
|
|
self.date = self.date.replace(day = days_range[1], minute = 59, second = 59)
|
|
self.first = not self.first
|
|
else:
|
|
self.date += datetime.timedelta(days = 1)
|
|
if (self.date.month == 1):
|
|
self.year_id += 1
|
|
if (len(self.years) == self.year_id):
|
|
# All years were processed, no need to calc next date
|
|
return
|
|
self.date = self.date.replace(year = self.years[self.year_id])
|
|
self.date = self.date.replace(day = 1, minute = 0, second = 0)
|
|
self.first = not self.first
|
|
|
|
def setup(self):
|
|
self.register_callback('timestamp', self._verify_timestamp)
|
|
self.register_callback('leap_year_setup', self._set_leap_year_support)
|