• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

payjoin / rust-payjoin / 12778748257

15 Jan 2025 12:12AM UTC coverage: 61.291% (+0.5%) from 60.758%
12778748257

Pull #484

github

web-flow
Merge 1f4e73721 into 34ee78d44
Pull Request #484: Expose test helpers

74 of 79 new or added lines in 1 file covered. (93.67%)

2991 of 4880 relevant lines covered (61.29%)

948.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.67
/payjoin/src/test_utils.rs
1
use std::env;
2
use std::sync::Arc;
3
use std::time::Duration;
4

5
use bitcoin::Amount;
6
use bitcoind::bitcoincore_rpc::json::AddressType;
7
use bitcoind::bitcoincore_rpc::{self, RpcApi};
8
use http::StatusCode;
9
use log::{log_enabled, Level};
10
use once_cell::sync::OnceCell;
11
use reqwest::{Client, ClientBuilder};
12
use tracing_subscriber::{EnvFilter, FmtSubscriber};
13
use url::Url;
14

15
pub type BoxError = Box<dyn std::error::Error + 'static>;
16
pub type BoxSendSyncError = Box<dyn std::error::Error + Send + Sync>;
17

18
static INIT_TRACING: OnceCell<()> = OnceCell::new();
19

20
pub fn init_tracing() {
18✔
21
    INIT_TRACING.get_or_init(|| {
18✔
22
        let subscriber = FmtSubscriber::builder()
3✔
23
            .with_env_filter(EnvFilter::from_default_env())
3✔
24
            .with_test_writer()
3✔
25
            .finish();
3✔
26

3✔
27
        tracing::subscriber::set_global_default(subscriber)
3✔
28
            .expect("failed to set global default subscriber");
3✔
29
    });
18✔
30
}
18✔
31

32
pub async fn init_directory(
6✔
33
    db_host: String,
6✔
34
    local_cert_key: (Vec<u8>, Vec<u8>),
6✔
35
) -> std::result::Result<
6✔
36
    (u16, tokio::task::JoinHandle<std::result::Result<(), BoxSendSyncError>>),
6✔
37
    BoxSendSyncError,
6✔
38
> {
6✔
39
    println!("Database running on {}", db_host);
6✔
40
    let timeout = Duration::from_secs(2);
6✔
41
    payjoin_directory::listen_tcp_with_tls_on_free_port(db_host, timeout, local_cert_key).await
6✔
42
}
6✔
43

44
// generates or gets a DER encoded localhost cert and key.
45
pub fn local_cert_key() -> (Vec<u8>, Vec<u8>) {
6✔
46
    let cert =
6✔
47
        rcgen::generate_simple_self_signed(vec!["0.0.0.0".to_string(), "localhost".to_string()])
6✔
48
            .expect("Failed to generate cert");
6✔
49
    let cert_der = cert.serialize_der().expect("Failed to serialize cert");
6✔
50
    let key_der = cert.serialize_private_key_der();
6✔
51
    (cert_der, key_der)
6✔
52
}
6✔
53

54
pub fn init_bitcoind_sender_receiver(
18✔
55
    sender_address_type: Option<AddressType>,
18✔
56
    receiver_address_type: Option<AddressType>,
18✔
57
) -> Result<(bitcoind::BitcoinD, bitcoincore_rpc::Client, bitcoincore_rpc::Client), BoxError> {
18✔
58
    let bitcoind_exe =
18✔
59
        env::var("BITCOIND_EXE").ok().or_else(|| bitcoind::downloaded_exe_path().ok()).unwrap();
18✔
60
    let mut conf = bitcoind::Conf::default();
18✔
61
    conf.view_stdout = log_enabled!(Level::Debug);
18✔
62
    let bitcoind = bitcoind::BitcoinD::with_conf(bitcoind_exe, &conf)?;
18✔
63
    let receiver = bitcoind.create_wallet("receiver")?;
18✔
64
    let receiver_address = receiver.get_new_address(None, receiver_address_type)?.assume_checked();
18✔
65
    let sender = bitcoind.create_wallet("sender")?;
18✔
66
    let sender_address = sender.get_new_address(None, sender_address_type)?.assume_checked();
18✔
67
    bitcoind.client.generate_to_address(1, &receiver_address)?;
18✔
68
    bitcoind.client.generate_to_address(101, &sender_address)?;
18✔
69

70
    assert_eq!(
18✔
71
        Amount::from_btc(50.0)?,
18✔
72
        receiver.get_balances()?.mine.trusted,
18✔
NEW
73
        "receiver doesn't own bitcoin"
×
74
    );
75

76
    assert_eq!(
18✔
77
        Amount::from_btc(50.0)?,
18✔
78
        sender.get_balances()?.mine.trusted,
18✔
NEW
79
        "sender doesn't own bitcoin"
×
80
    );
81
    Ok((bitcoind, sender, receiver))
18✔
82
}
18✔
83

84
pub fn http_agent(cert_der: Vec<u8>) -> Result<Client, BoxError> {
6✔
85
    Ok(http_agent_builder(cert_der)?.build()?)
6✔
86
}
6✔
87

88
fn http_agent_builder(cert_der: Vec<u8>) -> Result<ClientBuilder, BoxError> {
6✔
89
    Ok(ClientBuilder::new()
6✔
90
        .danger_accept_invalid_certs(true)
6✔
91
        .use_rustls_tls()
6✔
92
        .add_root_certificate(reqwest::tls::Certificate::from_der(cert_der.as_slice()).unwrap()))
6✔
93
}
6✔
94

95
const TESTS_TIMEOUT: Duration = Duration::from_secs(20);
96
const WAIT_SERVICE_INTERVAL: Duration = Duration::from_secs(3);
97

98
pub async fn wait_for_service_ready(
11✔
99
    service_url: Url,
11✔
100
    agent: Arc<Client>,
11✔
101
) -> Result<(), &'static str> {
11✔
102
    let health_url = service_url.join("/health").map_err(|_| "Invalid URL")?;
11✔
103
    let start = std::time::Instant::now();
11✔
104

105
    while start.elapsed() < TESTS_TIMEOUT {
11✔
106
        let request_result =
11✔
107
            agent.get(health_url.as_str()).send().await.map_err(|_| "Bad request")?;
11✔
108
        match request_result.status() {
11✔
109
            StatusCode::OK => return Ok(()),
11✔
NEW
110
            StatusCode::NOT_FOUND => return Err("Endpoint not found"),
×
NEW
111
            _ => std::thread::sleep(WAIT_SERVICE_INTERVAL),
×
112
        }
113
    }
114

NEW
115
    Err("Timeout waiting for service to be ready")
×
116
}
11✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc