+pub struct TestScorer {
+ /// Stores a tuple of (scid, ChannelUsage)
+ scorer_expectations: RefCell<Option<VecDeque<(u64, ChannelUsage)>>>,
+}
+
+impl TestScorer {
+ pub fn new() -> Self {
+ Self {
+ scorer_expectations: RefCell::new(None),
+ }
+ }
+
+ pub fn expect_usage(&self, scid: u64, expectation: ChannelUsage) {
+ self.scorer_expectations.borrow_mut().get_or_insert_with(|| VecDeque::new()).push_back((scid, expectation));
+ }
+}
+
+#[cfg(c_bindings)]
+impl crate::util::ser::Writeable for TestScorer {
+ fn write<W: crate::util::ser::Writer>(&self, _: &mut W) -> Result<(), crate::io::Error> { unreachable!(); }
+}
+
+impl Score for TestScorer {
+ fn channel_penalty_msat(
+ &self, short_channel_id: u64, _source: &NodeId, _target: &NodeId, usage: ChannelUsage
+ ) -> u64 {
+ if let Some(scorer_expectations) = self.scorer_expectations.borrow_mut().as_mut() {
+ match scorer_expectations.pop_front() {
+ Some((scid, expectation)) => {
+ assert_eq!(expectation, usage);
+ assert_eq!(scid, short_channel_id);
+ },
+ None => {},
+ }
+ }
+ 0
+ }
+
+ fn payment_path_failed(&mut self, _actual_path: &[&RouteHop], _actual_short_channel_id: u64) {}
+
+ fn payment_path_successful(&mut self, _actual_path: &[&RouteHop]) {}
+
+ fn probe_failed(&mut self, _actual_path: &[&RouteHop], _: u64) {}
+
+ fn probe_successful(&mut self, _actual_path: &[&RouteHop]) {}
+}
+
+impl Drop for TestScorer {
+ fn drop(&mut self) {
+ #[cfg(feature = "std")] {
+ if std::thread::panicking() {
+ return;
+ }
+ }
+
+ if let Some(scorer_expectations) = self.scorer_expectations.borrow().as_ref() {
+ if !scorer_expectations.is_empty() {
+ panic!("Unsatisfied scorer expectations: {:?}", scorer_expectations)
+ }
+ }
+ }
+}