Skip to content

Commit c610c34

Browse files
grunchclaude
andauthored
fix(price): repair test-only price seeding broken by #753/#770 merge skew (#774)
PR #753 removed the BITCOIN_PRICES static when it migrated price reads to the PriceManager, while PR #770 (merged independently) added BitcoinPriceManager::set_price_for_test writing to that static — the combination doesn't compile under cargo test on main. Re-point the test seam at a small cfg(test) override map consulted by price::get_bitcoin_price before the global manager, so unit tests keep seeding deterministic prices without installing the global PriceManager (whose OnceLock would leak one test's configuration into the rest of the binary). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent af8f05d commit c610c34

3 files changed

Lines changed: 33 additions & 7 deletions

File tree

src/bitcoin_price.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,17 @@ impl BitcoinPriceManager {
2121
crate::price::get_bitcoin_price(currency)
2222
}
2323

24-
/// Test-only: seed the in-memory price cache so unit tests in other
25-
/// modules can exercise price-dependent paths (e.g. range-order bond
26-
/// sizing) deterministically without hitting the network. Use a unique
27-
/// `currency` per test to avoid cross-test interference on the shared
28-
/// static.
24+
/// Test-only: seed the price-override map consulted by
25+
/// [`crate::price::get_bitcoin_price`] so unit tests in other modules
26+
/// can exercise price-dependent paths (e.g. range-order bond sizing)
27+
/// deterministically without hitting the network or installing the
28+
/// global `PriceManager`. Use a unique `currency` per test to avoid
29+
/// cross-test interference on the shared map.
2930
#[cfg(test)]
3031
pub(crate) fn set_price_for_test(currency: &str, price: f64) {
31-
BITCOIN_PRICES
32+
crate::price::test_price_overrides()
3233
.write()
33-
.expect("price cache write lock")
34+
.expect("price override write lock")
3435
.insert(currency.to_string(), price);
3536
}
3637
}

src/price/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,22 @@ pub use store::{AggregatedPrice, PriceError, PriceStore};
2727

2828
use mostro_core::error::{MostroError, ServiceError};
2929

30+
/// Test-only per-currency price overrides consulted by
31+
/// [`get_bitcoin_price`] before the global manager. Unit tests in other
32+
/// modules (e.g. range-order bond sizing in `util.rs`) seed this via
33+
/// `BitcoinPriceManager::set_price_for_test` instead of installing the
34+
/// global [`PriceManager`] — its `OnceLock` would leak one test's
35+
/// configuration into every other test in the binary. Tests use a unique
36+
/// currency code each to avoid cross-test interference on the shared map.
37+
#[cfg(test)]
38+
pub(crate) fn test_price_overrides(
39+
) -> &'static std::sync::RwLock<std::collections::HashMap<String, f64>> {
40+
static OVERRIDES: std::sync::OnceLock<
41+
std::sync::RwLock<std::collections::HashMap<String, f64>>,
42+
> = std::sync::OnceLock::new();
43+
OVERRIDES.get_or_init(|| std::sync::RwLock::new(std::collections::HashMap::new()))
44+
}
45+
3046
/// Read a currency's per-BTC price from the global [`PriceManager`].
3147
///
3248
/// This is the Phase 1 entry point for consumers (`util::get_bitcoin_price`
@@ -36,6 +52,14 @@ use mostro_core::error::{MostroError, ServiceError};
3652
/// legacy code returned when `BITCOIN_PRICES` was empty, so callers behave
3753
/// identically.
3854
pub fn get_bitcoin_price(currency: &str) -> Result<f64, MostroError> {
55+
#[cfg(test)]
56+
if let Some(price) = test_price_overrides()
57+
.read()
58+
.expect("price override read lock")
59+
.get(currency)
60+
{
61+
return Ok(*price);
62+
}
3963
match PriceManager::global() {
4064
Some(m) => m.get_price(currency),
4165
None => Err(MostroError::MostroInternalErr(ServiceError::NoAPIResponse)),

src/util.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,6 +1598,7 @@ pub async fn notify_taker_reputation(
15981598
#[cfg(test)]
15991599
mod tests {
16001600
use super::*;
1601+
use crate::bitcoin_price::BitcoinPriceManager;
16011602
use mostro_core::message::{Message, MessageKind};
16021603
use mostro_core::order::Order;
16031604
use sqlx::sqlite::SqlitePoolOptions;

0 commit comments

Comments
 (0)