Skip to content

Commit 8fe6720

Browse files
committed
maybe fix
1 parent db5fa57 commit 8fe6720

2 files changed

Lines changed: 71 additions & 14 deletions

File tree

.github/workflows/ci.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,9 @@ jobs:
4141
- name: Run Test Suite
4242
env:
4343
BITCOIN_BIN: ${{ github.workspace }}/bitcoin/build/bin/bitcoin
44-
run: cargo test
44+
run: |
45+
tests="$(cargo test --test test -- --list | sed -n 's/: test$//p')"
46+
while IFS= read -r test_name; do
47+
[ -n "$test_name" ] || continue
48+
cargo test --test test -- --exact --test-threads=1 "$test_name"
49+
done <<< "$tests"

tests/util/bitcoin_core_wallet.rs

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
use std::process::Command;
1+
use std::{
2+
io::Read,
3+
process::{Command, Stdio},
4+
time::{Duration, Instant},
5+
};
26

37
use bitcoin_primitives::Transaction as BitcoinTransaction;
48
use bitcoin_primitives::hex;
@@ -9,6 +13,16 @@ fn bitcoin_bin() -> String {
913
std::env::var("BITCOIN_BIN").unwrap_or_else(|_| "bitcoin".to_owned())
1014
}
1115

16+
fn bitcoin_rpc_timeout() -> Duration {
17+
const DEFAULT_TIMEOUT_SECS: u64 = 15;
18+
19+
std::env::var("BITCOIN_RPC_TIMEOUT_SECS")
20+
.ok()
21+
.and_then(|secs| secs.parse::<u64>().ok())
22+
.map(Duration::from_secs)
23+
.unwrap_or_else(|| Duration::from_secs(DEFAULT_TIMEOUT_SECS))
24+
}
25+
1226
fn bitcoin_rpc(wallet: Option<&str>, args: &[&str]) -> Result<String, String> {
1327
let owned_args: Vec<String> = args.iter().map(|arg| (*arg).to_owned()).collect();
1428
bitcoin_rpc_owned(wallet, &owned_args)
@@ -34,19 +48,57 @@ fn bitcoin_rpc_owned(wallet: Option<&str>, args: &[String]) -> Result<String, St
3448
}
3549
command.args(args);
3650

37-
let output = command
38-
.output()
51+
let rendered_args = args.join(" ");
52+
let timeout = bitcoin_rpc_timeout();
53+
command.stdout(Stdio::piped()).stderr(Stdio::piped());
54+
55+
let mut child = command
56+
.spawn()
3957
.map_err(|e| format!("failed to execute bitcoin rpc command: {e}"))?;
40-
if output.status.success() {
41-
Ok(String::from_utf8(output.stdout)
42-
.unwrap_or_else(|_| String::new())
43-
.trim()
44-
.to_owned())
45-
} else {
46-
Err(format!(
47-
"bitcoin rpc command failed: {}",
48-
String::from_utf8_lossy(&output.stderr).trim()
49-
))
58+
let start = Instant::now();
59+
60+
loop {
61+
match child.try_wait() {
62+
Ok(Some(status)) => {
63+
let mut stdout = Vec::new();
64+
let mut stderr = Vec::new();
65+
if let Some(mut pipe) = child.stdout.take() {
66+
pipe.read_to_end(&mut stdout)
67+
.map_err(|e| format!("failed to read bitcoin rpc stdout: {e}"))?;
68+
}
69+
if let Some(mut pipe) = child.stderr.take() {
70+
pipe.read_to_end(&mut stderr)
71+
.map_err(|e| format!("failed to read bitcoin rpc stderr: {e}"))?;
72+
}
73+
74+
if status.success() {
75+
return Ok(String::from_utf8(stdout)
76+
.unwrap_or_else(|_| String::new())
77+
.trim()
78+
.to_owned());
79+
}
80+
81+
return Err(format!(
82+
"bitcoin rpc command failed ({rendered_args}): {}",
83+
String::from_utf8_lossy(&stderr).trim()
84+
));
85+
}
86+
Ok(None) => {
87+
if start.elapsed() >= timeout {
88+
let _ = child.kill();
89+
let _ = child.wait();
90+
return Err(format!(
91+
"bitcoin rpc command timed out after {timeout:?} ({rendered_args})"
92+
));
93+
}
94+
std::thread::sleep(Duration::from_millis(100));
95+
}
96+
Err(e) => {
97+
let _ = child.kill();
98+
let _ = child.wait();
99+
return Err(format!("failed to poll bitcoin rpc command status: {e}"));
100+
}
101+
}
50102
}
51103
}
52104

0 commit comments

Comments
 (0)