use anyhow::Result;
use solana_sdk::clock::Clock;
use crate::context::TestContext;
const SLOT_DURATION_MS: i64 = 400;
pub fn advance_clock(ctx: &TestContext, seconds: i64) -> Result<()> {
if seconds < 0 {
anyhow::bail!("advance_clock does not support negative seconds; use set_clock instead");
}
let mut svm = ctx.lock_svm();
let mut clock = svm.get_sysvar::<Clock>();
clock.unix_timestamp = clock
.unix_timestamp
.checked_add(seconds)
.ok_or_else(|| anyhow::anyhow!("unix_timestamp overflow when advancing by {seconds}s"))?;
let slot_delta = (seconds * 1000) / SLOT_DURATION_MS;
let slot_delta_u64 = u64::try_from(slot_delta)
.map_err(|_| anyhow::anyhow!("negative slot delta: {slot_delta}"))?;
clock.slot = clock
.slot
.checked_add(slot_delta_u64)
.ok_or_else(|| anyhow::anyhow!("slot overflow when advancing by {slot_delta} slots"))?;
svm.set_sysvar::<Clock>(&clock);
Ok(())
}
pub fn set_clock(ctx: &TestContext, unix_timestamp: i64) -> Result<()> {
let mut svm = ctx.lock_svm();
let mut clock = svm.get_sysvar::<Clock>();
clock.unix_timestamp = unix_timestamp;
svm.set_sysvar::<Clock>(&clock);
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::context::new_test_context;
#[test]
fn test_advance_clock() {
let ctx = new_test_context().unwrap();
let before = {
let svm = ctx.lock_svm();
svm.get_sysvar::<Clock>().unix_timestamp
};
advance_clock(&ctx, 3600).unwrap();
let after = {
let svm = ctx.lock_svm();
svm.get_sysvar::<Clock>().unix_timestamp
};
assert_eq!(after - before, 3600);
}
#[test]
fn test_set_clock() {
let ctx = new_test_context().unwrap();
let target_ts: i64 = 1_700_000_000;
set_clock(&ctx, target_ts).unwrap();
let actual = {
let svm = ctx.lock_svm();
svm.get_sysvar::<Clock>().unix_timestamp
};
assert_eq!(actual, target_ts);
}
#[test]
fn test_advance_clock_updates_slot() {
let ctx = new_test_context().unwrap();
let slot_before = {
let svm = ctx.lock_svm();
svm.get_sysvar::<Clock>().slot
};
advance_clock(&ctx, 10).unwrap();
let slot_after = {
let svm = ctx.lock_svm();
svm.get_sysvar::<Clock>().slot
};
assert_eq!(slot_after - slot_before, 25);
}
}