From 092af13298befa2290eb34e2e81a2017a4ce2b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Poulhi=C3=A8s?= Date: Wed, 17 Jun 2020 16:05:34 +0200 Subject: [PATCH] Better detect incorrect input for alarms, refactor some test macros Alarm can be triggered on a subset of input, no need to reject ignored fields (eg. don't care about day field when matching on time only). We still need to set these to correct values as they are still used to set alarm registers. Test macro have been refactored to accept variable number of arguments. --- src/ds323x/alarms.rs | 161 +++++++++++++-- tests/alarms.rs | 460 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 507 insertions(+), 114 deletions(-) diff --git a/src/ds323x/alarms.rs b/src/ds323x/alarms.rs index 9774794..d5b91f2 100644 --- a/src/ds323x/alarms.rs +++ b/src/ds323x/alarms.rs @@ -5,6 +5,12 @@ use super::{decimal_to_packed_bcd, hours_to_register}; use interface::{ReadData, WriteData}; /// Parameters for setting Alarm1 on a day of the month +/// +/// Depending on the matching strategy, some fields may not be relevant. In this +/// case, invalid values are ignored and basic values are used instead to +/// configure the alarm: +/// - second, minute and hour : 0 +/// - day: 1 #[derive(Debug, Clone, Copy, PartialEq)] pub struct DayAlarm1 { /// Day of the month [1-31] @@ -18,6 +24,12 @@ pub struct DayAlarm1 { } /// Parameters for setting Alarm1 on a weekday +/// +/// Depending on the matching strategy, some fields may not be relevant. In this +/// case, invalid values are ignored and basic values are used instead to +/// configure the alarm: +/// - second, minute and hour : 0 +/// - weekday: 1 #[derive(Debug, Clone, Copy, PartialEq)] pub struct WeekdayAlarm1 { /// Weekday [1-7] @@ -46,6 +58,12 @@ pub enum Alarm1Matching { } /// Parameters for setting Alarm2 on a day of the month +/// +/// Depending on the matching strategy, some fields may not be relevant. In this +/// case, invalid values are ignored and basic values are used instead to +/// configure the alarm: +/// - minute and hour : 0 +/// - day: 1 #[derive(Debug, Clone, Copy, PartialEq)] pub struct DayAlarm2 { /// Day of month [1-31] @@ -57,6 +75,12 @@ pub struct DayAlarm2 { } /// Parameters for setting Alarm2 on a weekday +/// +/// Depending on the matching strategy, some fields may not be relevant. In this +/// case, invalid values are ignored and basic values are used instead to +/// configure the alarm: +/// - minute and hour : 0 +/// - weekday: 1 #[derive(Debug, Clone, Copy, PartialEq)] pub struct WeekdayAlarm2 { /// Weekday [1-7] @@ -101,92 +125,187 @@ fn get_matching_mask_alarm2(matching: Alarm2Matching) -> [u8; 3] { } } +/// Test if hours value is valid +/// +/// Will return true if valid, false if not +fn is_hour_valid(hours: Hours) -> bool { + match hours { + Hours::H24(h) if h > 23 => true, + Hours::AM(h) if h < 1 || h > 12 => true, + Hours::PM(h) if h < 1 || h > 12 => true, + _ => false, + } +} + +/// Relax the hour value by changing an incorrect value by 0 +fn relax_hour(hours: Hours) -> Hours { + match hours { + Hours::H24(h) if h > 23 => Hours::H24(0), + Hours::H24(h) => Hours::H24(h), + Hours::AM(h) if h < 1 || h > 12 => Hours::AM(1), + Hours::AM(h) => Hours::AM(h), + Hours::PM(h) if h < 1 || h > 12 => Hours::PM(1), + Hours::PM(h) => Hours::PM(h), + } +} + impl Ds323x where DI: ReadData> + WriteData>, { /// Set Alarm1 for day of the month. /// - /// Will return an `Error::InvalidInputData` if any of the parameters is out of range. + /// Will return an `Error::InvalidInputData` if any of the used parameters + /// (depending on the matching startegy) is out of range. Any unused + /// parameter is set to basic valid value: + /// - second, minute, hour: 0 + /// - day: 1 pub fn set_alarm1_day( &mut self, when: DayAlarm1, matching: Alarm1Matching, ) -> Result<(), Error> { - if when.day < 1 || when.day > 31 || when.minute > 59 || when.second > 59 { + let day_invalid = when.day < 1 || when.day > 31; + let hour_invalid = is_hour_valid(when.hour); + let minute_invalid = when.minute > 59; + let second_invalid = when.second > 59; + + let day = if day_invalid { 1 } else { when.day }; + let hour = relax_hour(when.hour); + let minute = if minute_invalid { 0 } else { when.minute }; + + if (matching == Alarm1Matching::AllMatch && (day_invalid || hour_invalid)) + || (hour_invalid && matching == Alarm1Matching::HoursMinutesAndSecondsMatch) + || ((matching != Alarm1Matching::SecondsMatch + && matching != Alarm1Matching::OncePerSecond) + && minute_invalid) + || second_invalid + { return Err(Error::InvalidInputData); } + let match_mask = get_matching_mask_alarm1(matching); let mut data = [ Register::ALARM1_SECONDS, decimal_to_packed_bcd(when.second) | match_mask[0], - decimal_to_packed_bcd(when.minute) | match_mask[1], - hours_to_register(when.hour)? | match_mask[2], - decimal_to_packed_bcd(when.day) | match_mask[3], + decimal_to_packed_bcd(minute) | match_mask[1], + hours_to_register(hour)? | match_mask[2], + decimal_to_packed_bcd(day) | match_mask[3], ]; self.iface.write_data(&mut data) } /// Set Alarm1 for weekday. /// - /// Will return an `Error::InvalidInputData` if any of the parameters is out of range. + /// Will return an `Error::InvalidInputData` if any of the used parameters + /// (depending on the matching startegy) is out of range. Any unused + /// parameter is set to basic valid value: + /// - second, minute, hour: 0 + /// - weekday: 1 pub fn set_alarm1_weekday( &mut self, when: WeekdayAlarm1, matching: Alarm1Matching, ) -> Result<(), Error> { - if when.weekday < 1 || when.weekday > 7 || when.minute > 59 || when.second > 59 { + let weekday_invalid = when.weekday < 1 || when.weekday > 7; + let hour_invalid = is_hour_valid(when.hour); + let minute_invalid = when.minute > 59; + let second_invalid = when.second > 59; + + let weekday = if weekday_invalid { 1 } else { when.weekday }; + let hour = relax_hour(when.hour); + let minute = if minute_invalid { 0 } else { when.minute }; + let second = if second_invalid { 0 } else { when.second }; + + if ((hour_invalid || weekday_invalid) && matching == Alarm1Matching::AllMatch) + || (hour_invalid && matching == Alarm1Matching::HoursMinutesAndSecondsMatch) + || (minute_invalid + && (matching != Alarm1Matching::OncePerSecond + && matching != Alarm1Matching::SecondsMatch)) + || (second_invalid && matching != Alarm1Matching::OncePerSecond) + { return Err(Error::InvalidInputData); } let match_mask = get_matching_mask_alarm1(matching); let mut data = [ Register::ALARM1_SECONDS, - decimal_to_packed_bcd(when.second) | match_mask[0], - decimal_to_packed_bcd(when.minute) | match_mask[1], - hours_to_register(when.hour)? | match_mask[2], - decimal_to_packed_bcd(when.weekday) | match_mask[3] | BitFlags::WEEKDAY, + decimal_to_packed_bcd(second) | match_mask[0], + decimal_to_packed_bcd(minute) | match_mask[1], + hours_to_register(hour)? | match_mask[2], + decimal_to_packed_bcd(weekday) | match_mask[3] | BitFlags::WEEKDAY, ]; self.iface.write_data(&mut data) } /// Set Alarm2 for date (day of month). /// - /// Will return an `Error::InvalidInputData` if any of the parameters is out of range. + /// Will return an `Error::InvalidInputData` if any of the used parameters + /// (depending on the matching startegy) is out of range. Any unused + /// parameter is set to basic valid value: + /// - minute, hour: 0 + /// - day: 1 pub fn set_alarm2_day( &mut self, when: DayAlarm2, matching: Alarm2Matching, ) -> Result<(), Error> { - if when.day < 1 || when.day > 31 || when.minute > 59 { + let day_invalid = when.day < 1 || when.day > 31; + let hour_invalid = is_hour_valid(when.hour); + let minute_invalid = when.minute > 59; + + let day = if day_invalid { 1 } else { when.day }; + let hour = relax_hour(when.hour); + let minute = if minute_invalid { 0 } else { when.minute }; + + if ((day_invalid || hour_invalid) && matching == Alarm2Matching::AllMatch) + || (hour_invalid && matching == Alarm2Matching::HoursAndMinutesMatch) + || (matching != Alarm2Matching::OncePerMinute && minute_invalid) + { return Err(Error::InvalidInputData); } + let match_mask = get_matching_mask_alarm2(matching); let mut data = [ Register::ALARM2_MINUTES, - decimal_to_packed_bcd(when.minute) | match_mask[0], - hours_to_register(when.hour)? | match_mask[1], - decimal_to_packed_bcd(when.day) | match_mask[2], + decimal_to_packed_bcd(minute) | match_mask[0], + hours_to_register(hour)? | match_mask[1], + decimal_to_packed_bcd(day) | match_mask[2], ]; self.iface.write_data(&mut data) } /// Set Alarm2 for weekday. /// - /// Will return an `Error::InvalidInputData` if any of the parameters is out of range. + /// Will return an `Error::InvalidInputData` if any of the used parameters + /// (depending on the matching startegy) is out of range. Any unused + /// parameter is set to basic valid value: + /// - minute, hour: 0 + /// - weekday: 1 pub fn set_alarm2_weekday( &mut self, when: WeekdayAlarm2, matching: Alarm2Matching, ) -> Result<(), Error> { - if when.weekday < 1 || when.weekday > 7 || when.minute > 59 { + let weekday_invalid = when.weekday < 1 || when.weekday > 7; + let hour_invalid = is_hour_valid(when.hour); + let minute_invalid = when.minute > 59; + + let weekday = if weekday_invalid { 1 } else { when.weekday }; + let hour = relax_hour(when.hour); + let minute = if minute_invalid { 0 } else { when.minute }; + + if (matching == Alarm2Matching::AllMatch && (weekday_invalid || hour_invalid)) + || (matching == Alarm2Matching::HoursAndMinutesMatch && hour_invalid) + || (minute_invalid && matching != Alarm2Matching::OncePerMinute) + { return Err(Error::InvalidInputData); } let match_mask = get_matching_mask_alarm2(matching); let mut data = [ Register::ALARM2_MINUTES, - decimal_to_packed_bcd(when.minute) | match_mask[0], - hours_to_register(when.hour)? | match_mask[1], - decimal_to_packed_bcd(when.weekday) | match_mask[2] | BitFlags::WEEKDAY, + decimal_to_packed_bcd(minute) | match_mask[0], + hours_to_register(hour)? | match_mask[1], + decimal_to_packed_bcd(weekday) | match_mask[2] | BitFlags::WEEKDAY, ]; self.iface.write_data(&mut data) } diff --git a/tests/alarms.rs b/tests/alarms.rs index 6ebc786..c9f3908 100644 --- a/tests/alarms.rs +++ b/tests/alarms.rs @@ -14,18 +14,18 @@ use ds323x::{ #[macro_export] macro_rules! _set_invalid_alarm_test { - ($name:ident, $method:ident, $create_method:ident, $destroy_method:ident, $alarm:expr, $matching:expr) => { + ($name:ident, $method:ident, $create_method:ident, $destroy_method:ident, $( $value:expr ),+) => { #[test] fn $name() { let mut dev = $create_method(&[]); - assert_invalid_input_data!(dev.$method($alarm, $matching)); + assert_invalid_input_data!(dev.$method($($value),*)); $destroy_method(dev); } }; } macro_rules! set_invalid_alarm_test { - ($name:ident, $method:ident, $alarm:expr, $matching:expr) => { + ($name:ident, $method:ident, $( $value:expr ),+) => { mod $name { use super::*; _set_invalid_alarm_test!( @@ -33,24 +33,21 @@ macro_rules! set_invalid_alarm_test { $method, new_ds3231, destroy_ds3231, - $alarm, - $matching + $($value),* ); _set_invalid_alarm_test!( cannot_set_invalid_ds3232, $method, new_ds3232, destroy_ds3232, - $alarm, - $matching + $($value),* ); _set_invalid_alarm_test!( cannot_set_invalid_ds3234, $method, new_ds3234, destroy_ds3234, - $alarm, - $matching + $($value),* ); } }; @@ -80,6 +77,28 @@ mod alarm1 { }, A1M::AllMatch ); + set_invalid_alarm_test!( + day_invalid_second, + set_alarm1_day, + DayAlarm1 { + day: 1, + hour: Hours::H24(1), + minute: 59, + second: 60 + }, + A1M::SecondsMatch + ); + set_invalid_alarm_test!( + day_invalid_minute, + set_alarm1_day, + DayAlarm1 { + day: 1, + hour: Hours::H24(1), + minute: 60, + second: 10 + }, + A1M::MinutesAndSecondsMatch + ); set_invalid_alarm_test!( day_invalid_h, set_alarm1_day, @@ -91,6 +110,17 @@ mod alarm1 { }, A1M::AllMatch ); + set_invalid_alarm_test!( + day_invalid_h_hmasm, + set_alarm1_day, + DayAlarm1 { + day: 1, + hour: Hours::H24(24), + minute: 1, + second: 1 + }, + A1M::HoursMinutesAndSecondsMatch + ); set_invalid_alarm_test!( day_invalid_am1, set_alarm1_day, @@ -191,6 +221,18 @@ mod alarm1 { }, A1M::AllMatch ); + set_invalid_alarm_test!( + wd_invalid_h_hmasm, + set_alarm1_weekday, + WeekdayAlarm1 { + weekday: 1, + hour: Hours::H24(24), + minute: 1, + second: 1 + }, + A1M::HoursMinutesAndSecondsMatch + ); + set_invalid_alarm_test!( wd_invalid_am1, set_alarm1_weekday, @@ -257,10 +299,42 @@ mod alarm1 { }, A1M::AllMatch ); + set_invalid_alarm_test!( + wd_invalid_sec_sm, + set_alarm1_weekday, + WeekdayAlarm1 { + weekday: 1, + hour: Hours::H24(1), + minute: 1, + second: 60 + }, + A1M::SecondsMatch + ); + set_invalid_alarm_test!( + wd_invalid_min_masm, + set_alarm1_weekday, + WeekdayAlarm1 { + weekday: 1, + hour: Hours::H24(1), + minute: 60, + second: 1 + }, + A1M::MinutesAndSecondsMatch + ); } mod alarm2 { use super::*; + set_invalid_alarm_test!( + day_invalid_min_mm, + set_alarm2_day, + DayAlarm2 { + day: 1, + hour: Hours::H24(1), + minute: 60 + }, + A2M::MinutesMatch + ); set_invalid_alarm_test!( day_invalid_min, set_alarm2_day, @@ -281,6 +355,16 @@ mod alarm2 { }, A2M::AllMatch ); + set_invalid_alarm_test!( + day_invalid_h_hamm, + set_alarm2_day, + DayAlarm2 { + day: 1, + hour: Hours::H24(24), + minute: 1 + }, + A2M::HoursAndMinutesMatch + ); set_invalid_alarm_test!( day_invalid_am1, set_alarm2_day, @@ -342,6 +426,16 @@ mod alarm2 { A2M::AllMatch ); + set_invalid_alarm_test!( + wd_invalid_min_mm, + set_alarm2_weekday, + WeekdayAlarm2 { + weekday: 1, + hour: Hours::H24(1), + minute: 60 + }, + A2M::MinutesMatch + ); set_invalid_alarm_test!( wd_invalid_min, set_alarm2_weekday, @@ -362,6 +456,16 @@ mod alarm2 { }, A2M::AllMatch ); + set_invalid_alarm_test!( + wd_invalid_h_hmm, + set_alarm2_weekday, + WeekdayAlarm2 { + weekday: 1, + hour: Hours::H24(24), + minute: 1 + }, + A2M::HoursAndMinutesMatch + ); set_invalid_alarm_test!( wd_invalid_am1, set_alarm2_weekday, @@ -422,22 +526,32 @@ mod alarm2 { }, A2M::AllMatch ); + set_invalid_alarm_test!( + wd_invalid_minute, + set_alarm2_weekday, + WeekdayAlarm2 { + weekday: 1, + hour: Hours::H24(1), + minute: 60 + }, + A2M::HoursAndMinutesMatch + ); } macro_rules! _set_values_test { - ($name:ident, $method:ident, $create_method:ident, $destroy_method:ident, $value1:expr, $value2:expr, $transactions:expr) => { + ($name:ident, $method:ident, $create_method:ident, $destroy_method:ident, $transactions:expr, $( $value:expr ),+) => { #[test] fn $name() { let trans = $transactions; let mut dev = $create_method(&trans); - dev.$method($value1, $value2).unwrap(); + dev.$method($($value),*).unwrap(); $destroy_method(dev); } }; } macro_rules! set_values_test { - ($name:ident, $method:ident, $value1:expr, $value2:expr, $i2c_transactions:expr, $spi_transactions:expr) => { + ($name:ident, $method:ident, $i2c_transactions:expr, $spi_transactions:expr, $( $value:expr ),+) => { mod $name { use super::*; _set_values_test!( @@ -445,37 +559,36 @@ macro_rules! set_values_test { $method, new_ds3231, destroy_ds3231, - $value1, - $value2, - $i2c_transactions + $i2c_transactions, + $($value),* ); _set_values_test!( can_set_ds3232, $method, new_ds3232, destroy_ds3232, - $value1, - $value2, - $i2c_transactions + $i2c_transactions, + $($value),* ); _set_values_test!( can_set_ds3234, $method, new_ds3234, destroy_ds3234, - $value1, - $value2, - $spi_transactions + $spi_transactions, + $($value),* ); } }; } macro_rules! set_alarm_test { - ($name:ident, $method:ident, $alarm:expr, $matching:expr, $register:ident, [ $( $registers:expr ),+ ]) => { - set_values_test!($name, $method, $alarm, $matching, + ($name:ident, $method:ident, $register:ident, [ $( $registers:expr ),+ ], $( $value:expr ),+) => { + set_values_test!($name, $method, [ I2cTrans::write(DEV_ADDR, vec![Register::$register, $( $registers ),*]) ], - [ SpiTrans::write(vec![Register::$register + 0x80, $( $registers ),*]) ]); + [ SpiTrans::write(vec![Register::$register + 0x80, $( $registers ),*]) ], + $($value),* + ); }; } @@ -486,94 +599,146 @@ mod alarm1_day { set_alarm_test!( h24, set_alarm1_day, + ALARM1_SECONDS, + [4, 3, 2, 1], DayAlarm1 { day: 1, hour: Hours::H24(2), minute: 3, second: 4 }, - A1M::AllMatch, - ALARM1_SECONDS, - [4, 3, 2, 1] + A1M::AllMatch ); set_alarm_test!( am, set_alarm1_day, + ALARM1_SECONDS, + [4, 3, 0b0100_0010, 1], DayAlarm1 { day: 1, hour: Hours::AM(2), minute: 3, second: 4 }, - A1M::AllMatch, - ALARM1_SECONDS, - [4, 3, 0b0100_0010, 1] + A1M::AllMatch ); set_alarm_test!( pm, set_alarm1_day, + ALARM1_SECONDS, + [4, 3, 0b0110_0010, 1], DayAlarm1 { day: 1, hour: Hours::PM(2), minute: 3, second: 4 }, - A1M::AllMatch, - ALARM1_SECONDS, - [4, 3, 0b0110_0010, 1] + A1M::AllMatch ); set_alarm_test!( match_hms, set_alarm1_day, + ALARM1_SECONDS, + [4, 3, 2, AM | 1], DayAlarm1 { day: 1, hour: Hours::H24(2), minute: 3, second: 4 }, - A1M::HoursMinutesAndSecondsMatch, + A1M::HoursMinutesAndSecondsMatch + ); + set_alarm_test!( + match_hms_ignore_incorrect_day, + set_alarm1_day, ALARM1_SECONDS, - [4, 3, 2, AM | 1] + [4, 3, 2, AM | 1], + DayAlarm1 { + day: 0, + hour: Hours::H24(2), + minute: 3, + second: 4 + }, + A1M::HoursMinutesAndSecondsMatch + ); + set_alarm_test!( + match_ms_ignore_invalid_hour, + set_alarm1_day, + ALARM1_SECONDS, + [4, 3, AM | 0, AM | 1], + DayAlarm1 { + day: 1, + hour: Hours::H24(24), + minute: 3, + second: 4 + }, + A1M::MinutesAndSecondsMatch ); set_alarm_test!( match_ms, set_alarm1_day, + ALARM1_SECONDS, + [4, 3, AM | 2, AM | 1], DayAlarm1 { day: 1, hour: Hours::H24(2), minute: 3, second: 4 }, - A1M::MinutesAndSecondsMatch, + A1M::MinutesAndSecondsMatch + ); + set_alarm_test!( + match_ms_ignore_incorrect_day, + set_alarm1_day, ALARM1_SECONDS, - [4, 3, AM | 2, AM | 1] + [4, 3, AM | 2, AM | 1], + DayAlarm1 { + day: 0, + hour: Hours::H24(2), + minute: 3, + second: 4 + }, + A1M::MinutesAndSecondsMatch ); set_alarm_test!( match_s, set_alarm1_day, + ALARM1_SECONDS, + [4, AM | 3, AM | 2, AM | 1], DayAlarm1 { day: 1, hour: Hours::H24(2), minute: 3, second: 4 }, - A1M::SecondsMatch, + A1M::SecondsMatch + ); + set_alarm_test!( + match_s_ignore_incorrect_min, + set_alarm1_day, ALARM1_SECONDS, - [4, AM | 3, AM | 2, AM | 1] + [4, AM | 0, AM | 2, AM | 1], + DayAlarm1 { + day: 1, + hour: Hours::H24(2), + minute: 60, + second: 4 + }, + A1M::SecondsMatch ); set_alarm_test!( match_ops, set_alarm1_day, + ALARM1_SECONDS, + [AM | 4, AM | 3, AM | 2, AM | 1], DayAlarm1 { day: 1, hour: Hours::H24(2), minute: 3, second: 4 }, - A1M::OncePerSecond, - ALARM1_SECONDS, - [AM | 4, AM | 3, AM | 2, AM | 1] + A1M::OncePerSecond ); } @@ -582,94 +747,132 @@ mod alarm1_weekday { set_alarm_test!( h24, set_alarm1_weekday, + ALARM1_SECONDS, + [4, 3, 2, BF::WEEKDAY | 1], WeekdayAlarm1 { weekday: 1, hour: Hours::H24(2), minute: 3, second: 4 }, - A1M::AllMatch, - ALARM1_SECONDS, - [4, 3, 2, BF::WEEKDAY | 1] + A1M::AllMatch ); set_alarm_test!( am, set_alarm1_weekday, + ALARM1_SECONDS, + [4, 3, 0b0100_0010, BF::WEEKDAY | 1], WeekdayAlarm1 { weekday: 1, hour: Hours::AM(2), minute: 3, second: 4 }, - A1M::AllMatch, - ALARM1_SECONDS, - [4, 3, 0b0100_0010, BF::WEEKDAY | 1] + A1M::AllMatch ); set_alarm_test!( pm, set_alarm1_weekday, + ALARM1_SECONDS, + [4, 3, 0b0110_0010, BF::WEEKDAY | 1], WeekdayAlarm1 { weekday: 1, hour: Hours::PM(2), minute: 3, second: 4 }, - A1M::AllMatch, - ALARM1_SECONDS, - [4, 3, 0b0110_0010, BF::WEEKDAY | 1] + A1M::AllMatch + ); + set_alarm_test!( + match_hms_ignore_incorrect_wd, + set_alarm1_weekday, + ALARM1_SECONDS, + [4, 3, 2, AM | BF::WEEKDAY | 1], + WeekdayAlarm1 { + weekday: 0, + hour: Hours::H24(2), + minute: 3, + second: 4 + }, + A1M::HoursMinutesAndSecondsMatch ); - set_alarm_test!( match_hms, set_alarm1_weekday, + ALARM1_SECONDS, + [4, 3, 2, AM | BF::WEEKDAY | 1], WeekdayAlarm1 { weekday: 1, hour: Hours::H24(2), minute: 3, second: 4 }, - A1M::HoursMinutesAndSecondsMatch, - ALARM1_SECONDS, - [4, 3, 2, AM | BF::WEEKDAY | 1] + A1M::HoursMinutesAndSecondsMatch ); set_alarm_test!( match_ms, set_alarm1_weekday, + ALARM1_SECONDS, + [4, 3, AM | 2, AM | BF::WEEKDAY | 1], WeekdayAlarm1 { weekday: 1, hour: Hours::H24(2), minute: 3, second: 4 }, - A1M::MinutesAndSecondsMatch, - ALARM1_SECONDS, - [4, 3, AM | 2, AM | BF::WEEKDAY | 1] + A1M::MinutesAndSecondsMatch ); set_alarm_test!( match_s, set_alarm1_weekday, + ALARM1_SECONDS, + [4, AM | 3, AM | 2, AM | BF::WEEKDAY | 1], WeekdayAlarm1 { weekday: 1, hour: Hours::H24(2), minute: 3, second: 4 }, - A1M::SecondsMatch, + A1M::SecondsMatch + ); + set_alarm_test!( + match_s_ignore_incorrect_min, + set_alarm1_weekday, ALARM1_SECONDS, - [4, AM | 3, AM | 2, AM | BF::WEEKDAY | 1] + [4, AM | 0, AM | 2, AM | BF::WEEKDAY | 1], + WeekdayAlarm1 { + weekday: 1, + hour: Hours::H24(2), + minute: 60, + second: 4 + }, + A1M::SecondsMatch ); set_alarm_test!( match_ops, set_alarm1_weekday, + ALARM1_SECONDS, + [AM | 4, AM | 3, AM | 2, AM | BF::WEEKDAY | 1], WeekdayAlarm1 { weekday: 1, hour: Hours::H24(2), minute: 3, second: 4 }, - A1M::OncePerSecond, + A1M::OncePerSecond + ); + set_alarm_test!( + match_ops_ignore_incorrect_sec, + set_alarm1_weekday, ALARM1_SECONDS, - [AM | 4, AM | 3, AM | 2, AM | BF::WEEKDAY | 1] + [AM | 0, AM | 3, AM | 2, AM | BF::WEEKDAY | 1], + WeekdayAlarm1 { + weekday: 1, + hour: Hours::H24(2), + minute: 3, + second: 60 + }, + A1M::OncePerSecond ); } @@ -678,75 +881,111 @@ mod alarm2_day { set_alarm_test!( h24, set_alarm2_day, + ALARM2_MINUTES, + [3, 2, 1], DayAlarm2 { day: 1, hour: Hours::H24(2), minute: 3 }, - A2M::AllMatch, - ALARM2_MINUTES, - [3, 2, 1] + A2M::AllMatch ); set_alarm_test!( am, set_alarm2_day, + ALARM2_MINUTES, + [3, 0b0100_0010, 1], DayAlarm2 { day: 1, hour: Hours::AM(2), minute: 3 }, - A2M::AllMatch, - ALARM2_MINUTES, - [3, 0b0100_0010, 1] + A2M::AllMatch ); set_alarm_test!( pm, set_alarm2_day, + ALARM2_MINUTES, + [3, 0b0110_0010, 1], DayAlarm2 { day: 1, hour: Hours::PM(2), minute: 3 }, - A2M::AllMatch, - ALARM2_MINUTES, - [3, 0b0110_0010, 1] + A2M::AllMatch ); set_alarm_test!( match_hm, set_alarm2_day, + ALARM2_MINUTES, + [3, 2, AM | 1], DayAlarm2 { day: 1, hour: Hours::H24(2), minute: 3 }, - A2M::HoursAndMinutesMatch, + A2M::HoursAndMinutesMatch + ); + set_alarm_test!( + match_hm_ignore_incorrect_day, + set_alarm2_day, ALARM2_MINUTES, - [3, 2, AM | 1] + [3, 2, AM | 1], + DayAlarm2 { + day: 0, + hour: Hours::H24(2), + minute: 3 + }, + A2M::HoursAndMinutesMatch ); set_alarm_test!( match_m, set_alarm2_day, + ALARM2_MINUTES, + [3, AM | 2, AM | 1], DayAlarm2 { day: 1, hour: Hours::H24(2), minute: 3 }, - A2M::MinutesMatch, + A2M::MinutesMatch + ); + set_alarm_test!( + match_m_ignore_invalid_h, + set_alarm2_day, ALARM2_MINUTES, - [3, AM | 2, AM | 1] + [3, AM | 0, AM | 1], + DayAlarm2 { + day: 1, + hour: Hours::H24(25), + minute: 3 + }, + A2M::MinutesMatch ); set_alarm_test!( match_opm, set_alarm2_day, + ALARM2_MINUTES, + [AM | 3, AM | 2, AM | 1], DayAlarm2 { day: 1, hour: Hours::H24(2), minute: 3 }, - A2M::OncePerMinute, + A2M::OncePerMinute + ); + set_alarm_test!( + match_opm_ignore_incorrect_min, + set_alarm2_day, ALARM2_MINUTES, - [AM | 3, AM | 2, AM | 1] + [AM | 0, AM | 2, AM | 1], + DayAlarm2 { + day: 1, + hour: Hours::H24(2), + minute: 60 + }, + A2M::OncePerMinute ); } @@ -755,74 +994,109 @@ mod alarm2_weekday { set_alarm_test!( h24, set_alarm2_weekday, + ALARM2_MINUTES, + [3, 2, BF::WEEKDAY | 1], WeekdayAlarm2 { weekday: 1, hour: Hours::H24(2), minute: 3 }, - A2M::AllMatch, - ALARM2_MINUTES, - [3, 2, BF::WEEKDAY | 1] + A2M::AllMatch ); set_alarm_test!( am, set_alarm2_weekday, + ALARM2_MINUTES, + [3, 0b0100_0010, BF::WEEKDAY | 1], WeekdayAlarm2 { weekday: 1, hour: Hours::AM(2), minute: 3 }, - A2M::AllMatch, - ALARM2_MINUTES, - [3, 0b0100_0010, BF::WEEKDAY | 1] + A2M::AllMatch ); set_alarm_test!( pm, set_alarm2_weekday, + ALARM2_MINUTES, + [3, 0b0110_0010, BF::WEEKDAY | 1], WeekdayAlarm2 { weekday: 1, hour: Hours::PM(2), minute: 3 }, - A2M::AllMatch, - ALARM2_MINUTES, - [3, 0b0110_0010, BF::WEEKDAY | 1] + A2M::AllMatch ); - set_alarm_test!( match_hm, set_alarm2_weekday, + ALARM2_MINUTES, + [3, 2, AM | BF::WEEKDAY | 1], WeekdayAlarm2 { weekday: 1, hour: Hours::H24(2), minute: 3 }, - A2M::HoursAndMinutesMatch, + A2M::HoursAndMinutesMatch + ); + set_alarm_test!( + match_hm_ignore_incorrect_wd, + set_alarm2_weekday, ALARM2_MINUTES, - [3, 2, AM | BF::WEEKDAY | 1] + [3, 2, AM | BF::WEEKDAY | 1], + WeekdayAlarm2 { + weekday: 0, + hour: Hours::H24(2), + minute: 3 + }, + A2M::HoursAndMinutesMatch ); set_alarm_test!( match_m, set_alarm2_weekday, + ALARM2_MINUTES, + [3, AM | 2, AM | BF::WEEKDAY | 1], WeekdayAlarm2 { weekday: 1, hour: Hours::H24(2), minute: 3 }, - A2M::MinutesMatch, + A2M::MinutesMatch + ); + set_alarm_test!( + match_m_ignore_invalid_hour, + set_alarm2_weekday, ALARM2_MINUTES, - [3, AM | 2, AM | BF::WEEKDAY | 1] + [3, AM | 0, AM | BF::WEEKDAY | 1], + WeekdayAlarm2 { + weekday: 1, + hour: Hours::H24(24), + minute: 3 + }, + A2M::MinutesMatch ); set_alarm_test!( match_opm, set_alarm2_weekday, + ALARM2_MINUTES, + [AM | 3, AM | 2, AM | BF::WEEKDAY | 1], WeekdayAlarm2 { weekday: 1, hour: Hours::H24(2), minute: 3 }, - A2M::OncePerMinute, + A2M::OncePerMinute + ); + set_alarm_test!( + match_opm_ignore_incorrect_min, + set_alarm2_weekday, ALARM2_MINUTES, - [AM | 3, AM | 2, AM | BF::WEEKDAY | 1] + [AM | 0, AM | 2, AM | BF::WEEKDAY | 1], + WeekdayAlarm2 { + weekday: 1, + hour: Hours::H24(2), + minute: 60 + }, + A2M::OncePerMinute ); }