1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#[test]
fn svc_create_accepts_secs_at_cron_ceiling() {
let _home = TempHome::set();
// A value equal to the cron-derived ceiling (`*/5` -> 300s) is in force, not clamped, so it
// passes `reject_over_ceiling` (covering the `secs <= ceiling` arm for both fields). A
// duplicate-slug routine pre-seeded in the store makes the create fail *after* that check with a
// `Conflict`, so the assertion proves the ceiling check did not reject — without performing any
// crontab/disk mutation.
let store = store_with(vec![make_routine(
"at-ceiling-dupe",
"At Ceiling ZZZ",
1,
1,
)]);
let result = svc_create(
&store,
CreateRoutineRequest {
disabled_reason: None,
model: None,
goal: None,
schedule: "*/5 * * * *".into(),
schedules: vec![],
// Same slug as the pre-seeded routine.
title: " at ceiling ZZZ ".into(),
ttl_secs: Some(300),
max_runtime_secs: Some(300),
..valid_create_request()
},
);
assert!(matches!(result, Err(AppError::Conflict(_))));
}
#[test]
fn svc_update_rejects_ttl_above_current_schedule_ceiling() {
let _home = TempHome::set();
// No schedule supplied: the ceiling derives from the routine's *current* `*/5` schedule, so a
// 1800s ttl exceeds the 300s ceiling and is rejected without mutating the store (#468).
let store = store_with(vec![Routine {
schedule: "*/5 * * * *".to_string(),
schedules: vec![],
..make_routine("upd-ttl-ceiling", "Keep Ceiling", 1, 1)
}]);
let result = svc_update(
&store,
"upd-ttl-ceiling",
UpdateRoutineRequest {
disabled_reason: None,
model: None,
goal: None,
ttl_secs: Some(1800),
..empty_update_request()
},
);
assert!(matches!(result, Err(AppError::BadRequest(_))));
// The store value is untouched by the rejected update.
assert_eq!(
store
.lock()
.unwrap()
.get("upd-ttl-ceiling")
.unwrap()
.ttl_secs,
None
);
}
#[test]
fn svc_update_rejects_secs_above_new_schedule_ceiling() {
let _home = TempHome::set();
// A supplied schedule is the *effective* schedule for the ceiling: tightening a `@daily` routine
// to `*/5` while setting max_runtime 1800 exceeds the new 300s ceiling and is rejected (#468).
let store = store_with(vec![make_routine("upd-new-sched", "Keep New Sched", 1, 1)]);
let result = svc_update(
&store,
"upd-new-sched",
UpdateRoutineRequest {
disabled_reason: None,
model: None,
goal: None,
schedule: Some("*/5 * * * *".into()),
schedules: None,
max_runtime_secs: Some(1800),
..empty_update_request()
},
);
assert!(matches!(result, Err(AppError::BadRequest(_))));
}