Reorganize integration tests, simplify fn signatures
This commit is contained in:
@@ -104,7 +104,7 @@ impl WorkloadBounds {
|
||||
pub struct WorkloadTracker {
|
||||
total_counts: HashMap<ResidentId, u8>,
|
||||
type_counts: HashMap<(ResidentId, ShiftType), u8>,
|
||||
holidays: HashMap<ResidentId, u8>,
|
||||
holiday_counts: HashMap<ResidentId, u8>,
|
||||
}
|
||||
|
||||
impl WorkloadTracker {
|
||||
@@ -115,8 +115,8 @@ impl WorkloadTracker {
|
||||
.entry((r_id, slot.shift_type()))
|
||||
.or_insert(0) += 1;
|
||||
|
||||
if config.is_holiday_or_weekend_slot(slot.day.0) {
|
||||
*self.holidays.entry(r_id).or_insert(0) += 1;
|
||||
if config.is_holiday_or_weekend_slot(slot) {
|
||||
*self.holiday_counts.entry(r_id).or_insert(0) += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,8 +129,8 @@ impl WorkloadTracker {
|
||||
*count = count.saturating_sub(1);
|
||||
}
|
||||
|
||||
if config.is_holiday_or_weekend_slot(slot.day.0) {
|
||||
if let Some(count) = self.holidays.get_mut(&r_id) {
|
||||
if config.is_holiday_or_weekend_slot(slot) {
|
||||
if let Some(count) = self.holiday_counts.get_mut(&r_id) {
|
||||
*count = count.saturating_sub(1);
|
||||
}
|
||||
}
|
||||
@@ -141,7 +141,11 @@ impl WorkloadTracker {
|
||||
}
|
||||
|
||||
pub fn current_holiday_workload(&self, r_id: &ResidentId) -> u8 {
|
||||
*self.holidays.get(r_id).unwrap_or(&0)
|
||||
*self.holiday_counts.get(r_id).unwrap_or(&0)
|
||||
}
|
||||
|
||||
pub fn current_shift_type_workload(&self, r_id: &ResidentId, shift_type: ShiftType) -> u8 {
|
||||
*self.type_counts.get(&(*r_id, shift_type)).unwrap_or(&0)
|
||||
}
|
||||
|
||||
pub fn reached_workload_limit(&self, bounds: &WorkloadBounds, r_id: &ResidentId) -> bool {
|
||||
@@ -172,9 +176,8 @@ impl WorkloadTracker {
|
||||
&self,
|
||||
bounds: &WorkloadBounds,
|
||||
r_id: &ResidentId,
|
||||
slot: &Slot,
|
||||
shift_type: ShiftType,
|
||||
) -> bool {
|
||||
let shift_type = slot.shift_type();
|
||||
let current_load = self.type_counts.get(&(*r_id, shift_type)).unwrap_or(&0);
|
||||
|
||||
if let Some(&max) = bounds.max_by_shift_type.get(&(*r_id, shift_type)) {
|
||||
@@ -183,10 +186,6 @@ impl WorkloadTracker {
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub fn get_type_count(&self, r_id: &ResidentId, shift_type: ShiftType) -> u8 {
|
||||
*self.type_counts.get(&(*r_id, shift_type)).unwrap_or(&0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -194,85 +193,23 @@ mod tests {
|
||||
use crate::{
|
||||
config::UserConfig,
|
||||
fixtures::{complex_config, hard_config, minimal_config},
|
||||
resident::{Resident, ResidentId},
|
||||
resident::ResidentId,
|
||||
schedule::ShiftType,
|
||||
slot::{Day, ShiftPosition, Slot},
|
||||
workload::{WorkloadBounds, WorkloadTracker},
|
||||
};
|
||||
use rstest::{fixture, rstest};
|
||||
use rstest::rstest;
|
||||
|
||||
#[fixture]
|
||||
fn config() -> UserConfig {
|
||||
UserConfig::default().with_residents(vec![
|
||||
Resident::new(1, "R1").with_max_shifts(2),
|
||||
Resident::new(2, "R2").with_max_shifts(2),
|
||||
Resident::new(3, "R3").with_reduced_load(),
|
||||
Resident::new(4, "R4"),
|
||||
Resident::new(5, "R5"),
|
||||
])
|
||||
}
|
||||
|
||||
#[fixture]
|
||||
fn tracker() -> WorkloadTracker {
|
||||
WorkloadTracker::default()
|
||||
}
|
||||
// Testing WorkloadBounds
|
||||
|
||||
#[rstest]
|
||||
fn test_max_workloads(config: UserConfig) {
|
||||
let bounds = WorkloadBounds::new_with_config(&config);
|
||||
assert_eq!(2, bounds.max_workloads[&ResidentId(1)]);
|
||||
assert_eq!(2, bounds.max_workloads[&ResidentId(2)]);
|
||||
assert_eq!(13, bounds.max_workloads[&ResidentId(3)]);
|
||||
assert_eq!(14, bounds.max_workloads[&ResidentId(4)]);
|
||||
assert_eq!(14, bounds.max_workloads[&ResidentId(5)]);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn test_reached_workload_limit(mut tracker: WorkloadTracker, config: UserConfig) {
|
||||
let r_id = ResidentId(1);
|
||||
let mut bounds = WorkloadBounds::default();
|
||||
bounds.max_workloads.insert(r_id, 1);
|
||||
|
||||
let slot_1 = Slot::new(Day(1), ShiftPosition::First);
|
||||
let slot_2 = Slot::new(Day(2), ShiftPosition::First);
|
||||
|
||||
assert!(!tracker.reached_workload_limit(&bounds, &r_id,));
|
||||
|
||||
tracker.insert(r_id, &config, slot_1);
|
||||
assert!(tracker.reached_workload_limit(&bounds, &r_id,));
|
||||
|
||||
tracker.insert(r_id, &config, slot_2);
|
||||
assert!(tracker.reached_workload_limit(&bounds, &r_id,));
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn test_reached_holiday_limit(mut tracker: WorkloadTracker, config: UserConfig) {
|
||||
let r_id = ResidentId(1);
|
||||
let mut bounds = WorkloadBounds::default();
|
||||
bounds.max_holiday_shifts.insert(r_id, 1);
|
||||
|
||||
let sat = Slot::new(Day(11), ShiftPosition::First);
|
||||
let sun = Slot::new(Day(12), ShiftPosition::First);
|
||||
|
||||
assert!(!tracker.reached_holiday_limit(&bounds, &r_id));
|
||||
|
||||
tracker.insert(r_id, &config, sat);
|
||||
assert!(tracker.reached_holiday_limit(&bounds, &r_id));
|
||||
|
||||
tracker.insert(r_id, &config, sun);
|
||||
assert!(tracker.reached_holiday_limit(&bounds, &r_id));
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn test_backtracking_accuracy(mut tracker: WorkloadTracker, config: UserConfig) {
|
||||
let r_id = ResidentId(1);
|
||||
let slot = Slot::new(Day(1), ShiftPosition::First);
|
||||
|
||||
tracker.insert(r_id, &config, slot);
|
||||
assert_eq!(tracker.current_workload(&r_id), 1);
|
||||
|
||||
tracker.remove(r_id, &config, slot);
|
||||
assert_eq!(tracker.current_workload(&r_id), 0);
|
||||
fn test_max_workloads(minimal_config: UserConfig) {
|
||||
let bounds = WorkloadBounds::new_with_config(&minimal_config);
|
||||
assert_eq!(9, bounds.max_workloads[&ResidentId(1)]);
|
||||
assert_eq!(9, bounds.max_workloads[&ResidentId(2)]);
|
||||
assert_eq!(9, bounds.max_workloads[&ResidentId(3)]);
|
||||
assert_eq!(9, bounds.max_workloads[&ResidentId(4)]);
|
||||
assert_eq!(9, bounds.max_workloads[&ResidentId(5)]);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
@@ -468,4 +405,88 @@ mod tests {
|
||||
assert_eq!(5, *m.get(&(ResidentId(8), ShiftType::OpenSecond)).unwrap());
|
||||
assert_eq!(0, *m.get(&(ResidentId(8), ShiftType::Closed)).unwrap());
|
||||
}
|
||||
|
||||
// Testing WorkloadTracker
|
||||
|
||||
#[rstest]
|
||||
fn test_reached_workload_limit(minimal_config: UserConfig) {
|
||||
let mut tracker = WorkloadTracker::default();
|
||||
let r_id = ResidentId(1);
|
||||
let mut bounds = WorkloadBounds::default();
|
||||
bounds.max_workloads.insert(r_id, 1);
|
||||
let slot_1 = Slot::new(Day(1), ShiftPosition::First);
|
||||
let slot_2 = Slot::new(Day(2), ShiftPosition::First);
|
||||
|
||||
assert!(!tracker.reached_workload_limit(&bounds, &r_id));
|
||||
tracker.insert(r_id, &minimal_config, slot_1);
|
||||
assert!(tracker.reached_workload_limit(&bounds, &r_id));
|
||||
tracker.insert(r_id, &minimal_config, slot_2);
|
||||
assert!(tracker.reached_workload_limit(&bounds, &r_id));
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn test_reached_holiday_limit(minimal_config: UserConfig) {
|
||||
let mut tracker = WorkloadTracker::default();
|
||||
let r_id = ResidentId(1);
|
||||
let mut bounds = WorkloadBounds::default();
|
||||
bounds.max_holiday_shifts.insert(r_id, 1);
|
||||
let sat = Slot::new(Day(11), ShiftPosition::First);
|
||||
let sun = Slot::new(Day(12), ShiftPosition::First);
|
||||
|
||||
assert!(!tracker.reached_holiday_limit(&bounds, &r_id));
|
||||
tracker.insert(r_id, &minimal_config, sat);
|
||||
assert!(tracker.reached_holiday_limit(&bounds, &r_id));
|
||||
tracker.insert(r_id, &minimal_config, sun);
|
||||
assert!(tracker.reached_holiday_limit(&bounds, &r_id));
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn test_reached_shift_type_limit(minimal_config: UserConfig) {
|
||||
let mut tracker = WorkloadTracker::default();
|
||||
let r_id = ResidentId(1);
|
||||
let mut bounds = WorkloadBounds::default();
|
||||
bounds
|
||||
.max_by_shift_type
|
||||
.insert((r_id, ShiftType::OpenFirst), 1);
|
||||
let slot_1 = Slot::new(Day(1), ShiftPosition::First);
|
||||
let slot_2 = Slot::new(Day(3), ShiftPosition::First);
|
||||
let open_first = ShiftType::OpenFirst;
|
||||
|
||||
assert!(!tracker.reached_shift_type_limit(&bounds, &r_id, open_first));
|
||||
tracker.insert(r_id, &minimal_config, slot_1);
|
||||
assert!(tracker.reached_shift_type_limit(&bounds, &r_id, open_first));
|
||||
tracker.insert(r_id, &minimal_config, slot_2);
|
||||
assert!(tracker.reached_shift_type_limit(&bounds, &r_id, open_first));
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn test_backtracking_state(minimal_config: UserConfig) {
|
||||
let mut tracker = WorkloadTracker::default();
|
||||
let r_id = ResidentId(1);
|
||||
let sat = Slot::new(Day(11), ShiftPosition::First);
|
||||
let sun = Slot::new(Day(12), ShiftPosition::First);
|
||||
let open_first = ShiftType::OpenFirst;
|
||||
let closed = ShiftType::Closed;
|
||||
|
||||
tracker.insert(r_id, &minimal_config, sat);
|
||||
assert_eq!(1, tracker.current_workload(&r_id));
|
||||
assert_eq!(1, tracker.current_holiday_workload(&r_id));
|
||||
assert_eq!(1, tracker.current_shift_type_workload(&r_id, open_first));
|
||||
tracker.insert(r_id, &minimal_config, sun);
|
||||
assert_eq!(2, tracker.current_workload(&r_id));
|
||||
assert_eq!(2, tracker.current_holiday_workload(&r_id));
|
||||
assert_eq!(1, tracker.current_shift_type_workload(&r_id, open_first));
|
||||
assert_eq!(1, tracker.current_shift_type_workload(&r_id, closed));
|
||||
|
||||
tracker.remove(r_id, &minimal_config, sun);
|
||||
assert_eq!(1, tracker.current_workload(&r_id));
|
||||
assert_eq!(1, tracker.current_holiday_workload(&r_id));
|
||||
assert_eq!(1, tracker.current_shift_type_workload(&r_id, open_first));
|
||||
assert_eq!(0, tracker.current_shift_type_workload(&r_id, closed));
|
||||
tracker.remove(r_id, &minimal_config, sat);
|
||||
assert_eq!(0, tracker.current_workload(&r_id));
|
||||
assert_eq!(0, tracker.current_holiday_workload(&r_id));
|
||||
assert_eq!(0, tracker.current_shift_type_workload(&r_id, open_first));
|
||||
assert_eq!(0, tracker.current_shift_type_workload(&r_id, closed));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user