Skip to content

Commit 2a7d9c8

Browse files
committed
Add SinceEpoch time to test Scorer hermetically
In order to test Scorer hermetically, sleeps must be avoided. Add a SinceEpoch abstraction for manually advancing time. Implement the Time trait for SinceEpoch so that it can be used with ScorerUsingTime in tests.
1 parent c0bbd4d commit 2a7d9c8

File tree

1 file changed

+75
-0
lines changed

1 file changed

+75
-0
lines changed

lightning/src/routing/scorer.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ impl Time for std::time::Instant {
247247
}
248248

249249
/// A state in which time has no meaning.
250+
#[derive(Debug, PartialEq, Eq)]
250251
pub struct Eternity;
251252

252253
impl Time for Eternity {
@@ -320,3 +321,77 @@ impl<T: Time> Readable for ChannelFailure<T> {
320321
})
321322
}
322323
}
324+
325+
#[cfg(test)]
326+
mod tests {
327+
use super::{Eternity, ScoringParameters, ScorerUsingTime, Time};
328+
329+
use routing::Score;
330+
use routing::network_graph::NodeId;
331+
332+
use bitcoin::secp256k1::PublicKey;
333+
use core::cell::Cell;
334+
use core::ops::Sub;
335+
use core::time::Duration;
336+
337+
/// Time that can be advanced manually in tests.
338+
#[derive(Debug, PartialEq, Eq)]
339+
struct SinceEpoch(Duration);
340+
341+
impl SinceEpoch {
342+
thread_local! {
343+
static ELAPSED: Cell<Duration> = core::cell::Cell::new(Duration::from_secs(0));
344+
}
345+
346+
fn advance(duration: Duration) {
347+
Self::ELAPSED.with(|elapsed| elapsed.set(elapsed.get() + duration))
348+
}
349+
}
350+
351+
impl Time for SinceEpoch {
352+
fn now() -> Self {
353+
Self(Self::duration_since_epoch())
354+
}
355+
356+
fn duration_since_epoch() -> Duration {
357+
Self::ELAPSED.with(|elapsed| elapsed.get())
358+
}
359+
360+
fn elapsed(&self) -> Duration {
361+
Self::duration_since_epoch() - self.0
362+
}
363+
}
364+
365+
impl Sub<Duration> for SinceEpoch {
366+
type Output = Self;
367+
368+
fn sub(self, other: Duration) -> Self {
369+
Self(self.0 - other)
370+
}
371+
}
372+
373+
#[test]
374+
fn time_passes_when_advanced() {
375+
let now = SinceEpoch::now();
376+
assert_eq!(now.elapsed(), Duration::from_secs(0));
377+
378+
SinceEpoch::advance(Duration::from_secs(1));
379+
SinceEpoch::advance(Duration::from_secs(1));
380+
381+
let elapsed = now.elapsed();
382+
let later = SinceEpoch::now();
383+
384+
assert_eq!(elapsed, Duration::from_secs(2));
385+
assert_eq!(later - elapsed, now);
386+
}
387+
388+
#[test]
389+
fn time_never_passes_in_an_eternity() {
390+
let now = Eternity::now();
391+
let elapsed = now.elapsed();
392+
let later = Eternity::now();
393+
394+
assert_eq!(now.elapsed(), Duration::from_secs(0));
395+
assert_eq!(later - elapsed, now);
396+
}
397+
}

0 commit comments

Comments
 (0)