Skip to content

Commit 4f9301e

Browse files
committed
Merge rust-bitcoin#5437: units: Improve and test API surface
7cef310 Update the API files (Tobin C. Harding) 3adb97f units: Update API test (Tobin C. Harding) ce355b4 Implement Arbitrary for relative::LockTime (Tobin C. Harding) Pull request description: Since we implemented it the API test has gotten out of sync, unfortunately there is no obvious way to prevent this. - Patch 1: Add missing `Arbitrary` impl - Patch 2: Clean the `api` test. - Patch 3: Update the API files. I just used grep on the `units` directory to do the fixes. ACKs for top commit: apoelstra: ACK 7cef310; successfully ran local tests Tree-SHA512: ec3252b2ea63976792730d421ca3373d7eb983175c2d6b05c1972402a85ee7ed5344c61e4467a9f8974c5712b2dce2c07bdec5c2a143a88566be023fa653144e
2 parents 8b1c08f + 7cef310 commit 4f9301e

File tree

3 files changed

+101
-24
lines changed

3 files changed

+101
-24
lines changed

api/units/all-features.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,7 @@ impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::block::BlockMtpInterval
12611261
impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::locktime::absolute::Height
12621262
impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::locktime::absolute::LockTime
12631263
impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::locktime::absolute::MedianTimePast
1264+
impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::locktime::relative::LockTime
12641265
impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::locktime::relative::NumberOf512Seconds
12651266
impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::locktime::relative::NumberOfBlocks
12661267
impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::result::MathOp
@@ -2246,6 +2247,7 @@ pub fn bitcoin_units::locktime::absolute::error::ParseTimeError::clone(&self) ->
22462247
pub fn bitcoin_units::locktime::absolute::error::ParseTimeError::eq(&self, other: &bitcoin_units::locktime::absolute::error::ParseTimeError) -> bool
22472248
pub fn bitcoin_units::locktime::absolute::error::ParseTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
22482249
pub fn bitcoin_units::locktime::absolute::error::ParseTimeError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)>
2250+
pub fn bitcoin_units::locktime::relative::LockTime::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result<Self>
22492251
pub fn bitcoin_units::locktime::relative::LockTime::clone(&self) -> bitcoin_units::locktime::relative::LockTime
22502252
pub fn bitcoin_units::locktime::relative::LockTime::deserialize<D>(deserializer: D) -> core::result::Result<Self, <D as serde::de::Deserializer>::Error> where D: serde::de::Deserializer<'de>
22512253
pub fn bitcoin_units::locktime::relative::LockTime::eq(&self, other: &bitcoin_units::locktime::relative::LockTime) -> bool

units/src/locktime/relative/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,18 @@ impl fmt::Display for NumberOf512Seconds {
579579
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
580580
}
581581

582+
#[cfg(feature = "arbitrary")]
583+
impl<'a> Arbitrary<'a> for LockTime {
584+
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
585+
let choice = u.int_in_range(0..=1)?;
586+
587+
match choice {
588+
0 => Ok(Self::Blocks(NumberOfBlocks::arbitrary(u)?)),
589+
_ => Ok(Self::Time(NumberOf512Seconds::arbitrary(u)?)),
590+
}
591+
}
592+
}
593+
582594
#[cfg(feature = "arbitrary")]
583595
impl<'a> Arbitrary<'a> for NumberOfBlocks {
584596
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {

units/tests/api.rs

Lines changed: 87 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,36 @@ use arbitrary::{Arbitrary, Unstructured};
1414
// These imports test "typical" usage by user code.
1515
use bitcoin_units::locktime::{absolute, relative}; // Typical usage is `absolute::LockTime`.
1616
use bitcoin_units::{
17-
amount, block, fee_rate, locktime, parse_int, result, time, weight, Amount, BlockHeight,
18-
BlockHeightInterval, BlockMtp, BlockMtpInterval, BlockTime, FeeRate, NumOpResult, SignedAmount,
19-
Weight,
17+
amount, block, fee_rate, locktime, parse_int, result, sequence, time, weight, Amount,
18+
BlockHeight, BlockHeightInterval, BlockMtp, BlockMtpInterval, BlockTime, FeeRate, NumOpResult,
19+
Sequence, SignedAmount, Weight,
2020
};
2121

2222
/// A struct that includes all public non-error enums.
2323
#[derive(Debug)] // All public types implement Debug (C-DEBUG).
2424
struct Enums {
2525
a: amount::Denomination,
26-
b: NumOpResult<Amount>,
27-
c: result::MathOp,
26+
b: absolute::LockTime,
27+
c: relative::LockTime,
28+
d: result::MathOp,
29+
e: result::NumOpResult<Amount>,
2830
}
2931

3032
impl Enums {
3133
fn new() -> Self {
3234
Self {
3335
a: amount::Denomination::Bitcoin,
34-
b: NumOpResult::Valid(Amount::MAX),
35-
c: result::MathOp::Add,
36+
b: absolute::LockTime::Blocks(absolute::Height::MAX),
37+
c: relative::LockTime::Blocks(relative::NumberOfBlocks::MAX),
38+
d: result::MathOp::Add,
39+
e: result::NumOpResult::Valid(Amount::MAX),
3640
}
3741
}
3842
}
3943

4044
/// A struct that includes all public non-error structs.
4145
#[derive(Debug)] // All public types implement Debug (C-DEBUG).
46+
// Does not include encoders and decoders.
4247
struct Structs {
4348
// Full path to show alphabetic sort order.
4449
a: amount::Amount,
@@ -53,8 +58,9 @@ struct Structs {
5358
j: locktime::absolute::MedianTimePast,
5459
k: locktime::relative::NumberOf512Seconds,
5560
l: locktime::relative::NumberOfBlocks,
56-
m: time::BlockTime,
57-
n: weight::Weight,
61+
m: sequence::Sequence,
62+
n: time::BlockTime,
63+
o: weight::Weight,
5864
}
5965

6066
impl Structs {
@@ -72,8 +78,9 @@ impl Structs {
7278
j: absolute::MedianTimePast::MAX,
7379
k: relative::NumberOf512Seconds::MAX,
7480
l: relative::NumberOfBlocks::MAX,
75-
m: BlockTime::from_u32(u32::MAX),
76-
n: Weight::MAX,
81+
m: sequence::Sequence::MAX,
82+
n: BlockTime::from_u32(u32::MAX),
83+
o: Weight::MAX,
7784
}
7885
}
7986
}
@@ -119,9 +126,10 @@ struct Default {
119126
d: BlockMtpInterval,
120127
e: relative::NumberOf512Seconds,
121128
f: relative::NumberOfBlocks,
129+
g: Sequence,
122130
}
123131

124-
/// A struct that includes all public error types.
132+
/// A struct that includes all public error types (excl. decode errors).
125133
// These derives are the policy of `rust-bitcoin` not Rust API guidelines.
126134
#[derive(Debug, Clone, PartialEq, Eq)] // All public types implement Debug (C-DEBUG).
127135
struct Errors {
@@ -150,16 +158,30 @@ struct Errors {
150158
v: parse_int::UnprefixedHexError,
151159
}
152160

161+
/// A struct that includes all public decoder error types.
162+
// These derives are the policy of `rust-bitcoin` not Rust API guidelines.
163+
#[derive(Debug, Clone, PartialEq, Eq)] // All public types implement Debug (C-DEBUG).
164+
#[cfg(feature = "encoding")]
165+
struct DecoderErrors {
166+
a: amount::error::AmountDecoderError,
167+
b: block::BlockHeightDecoderError,
168+
c: locktime::absolute::LockTimeDecoderError,
169+
d: sequence::SequenceDecoderError,
170+
e: time::BlockTimeDecoderError,
171+
}
172+
153173
#[test]
154174
fn api_can_use_modules_from_crate_root() {
155-
use bitcoin_units::{amount, block, fee_rate, locktime, parse_int, time, weight};
175+
use bitcoin_units::{
176+
amount, block, fee_rate, locktime, parse_int, result, sequence, time, weight,
177+
};
156178
}
157179

158180
#[test]
159181
fn api_can_use_types_from_crate_root() {
160182
use bitcoin_units::{
161183
Amount, BlockHeight, BlockHeightInterval, BlockMtp, BlockMtpInterval, BlockTime, FeeRate,
162-
NumOpResult, SignedAmount, Weight,
184+
NumOpResult, Sequence, SignedAmount, Weight,
163185
};
164186
}
165187

@@ -169,13 +191,15 @@ fn api_can_use_all_types_from_module_amount() {
169191
Amount, Denomination, Display, OutOfRangeError, ParseAmountError, ParseDenominationError,
170192
ParseError, SignedAmount,
171193
};
194+
#[cfg(feature = "encoding")]
195+
use bitcoin_units::amount::{AmountDecoder, AmountDecoderError, AmountEncoder};
172196
}
173197

174198
#[test]
175199
fn api_can_use_all_types_from_module_amount_error() {
176200
use bitcoin_units::amount::error::{
177-
InputTooLargeError, InvalidCharacterError, MissingDenominationError, MissingDigitsError,
178-
OutOfRangeError, ParseAmountError, ParseDenominationError, ParseError,
201+
BadPositionError, InputTooLargeError, InvalidCharacterError, MissingDenominationError,
202+
MissingDigitsError, OutOfRangeError, ParseAmountError, ParseDenominationError, ParseError,
179203
PossiblyConfusingDenominationError, TooPreciseError, UnknownDenominationError,
180204
};
181205
}
@@ -185,6 +209,15 @@ fn api_can_use_all_types_from_module_block() {
185209
use bitcoin_units::block::{
186210
BlockHeight, BlockHeightInterval, BlockMtp, BlockMtpInterval, TooBigForRelativeHeightError,
187211
};
212+
#[cfg(feature = "encoding")]
213+
use bitcoin_units::block::{BlockHeightDecoder, BlockHeightDecoderError, BlockHeightEncoder};
214+
}
215+
216+
#[test]
217+
fn api_can_use_all_types_from_module_sequence() {
218+
use bitcoin_units::sequence::Sequence;
219+
#[cfg(feature = "encoding")]
220+
use bitcoin_units::sequence::{SequenceDecoder, SequenceDecoderError, SequenceEncoder};
188221
}
189222

190223
#[test]
@@ -196,21 +229,31 @@ fn api_can_use_all_types_from_module_fee_rate() {
196229

197230
#[test]
198231
fn api_can_use_all_types_from_module_locktime_absolute() {
232+
#[cfg(feature = "encoding")]
233+
use bitcoin_units::locktime::absolute::error::LockTimeDecoderError as _;
199234
use bitcoin_units::locktime::absolute::error::{
200-
ConversionError as _, ParseHeightError as _, ParseTimeError as _,
235+
ConversionError as _, IncompatibleHeightError as _, IncompatibleTimeError as _,
236+
ParseHeightError as _, ParseTimeError as _,
237+
};
238+
use bitcoin_units::locktime::absolute::{
239+
ConversionError, IncompatibleHeightError, IncompatibleTimeError, ParseHeightError,
240+
ParseTimeError,
201241
};
242+
#[cfg(feature = "encoding")]
202243
use bitcoin_units::locktime::absolute::{
203-
ConversionError, Height, MedianTimePast, ParseHeightError, ParseTimeError,
244+
LockTimeDecoder, LockTimeDecoderError, LockTimeEncoder,
204245
};
205246
}
206247

207248
#[test]
208249
fn api_can_use_all_types_from_module_locktime_relative() {
209250
use bitcoin_units::locktime::relative::error::{
210-
InvalidHeightError as _, InvalidTimeError as _, TimeOverflowError as _,
251+
DisabledLockTimeError as _, InvalidHeightError as _, InvalidTimeError as _,
252+
TimeOverflowError as _,
211253
};
212254
use bitcoin_units::locktime::relative::{
213-
InvalidHeightError, InvalidTimeError, NumberOf512Seconds, NumberOfBlocks, TimeOverflowError,
255+
DisabledLockTimeError, InvalidHeightError, InvalidTimeError, NumberOf512Seconds,
256+
NumberOfBlocks, TimeOverflowError,
214257
};
215258
}
216259

@@ -222,6 +265,8 @@ fn api_can_use_all_types_from_module_parse() {
222265
#[test]
223266
fn api_can_use_all_types_from_module_time() {
224267
use bitcoin_units::time::BlockTime;
268+
#[cfg(feature = "encoding")]
269+
use bitcoin_units::time::{BlockTimeDecoder, BlockTimeDecoderError, BlockTimeEncoder};
225270
}
226271

227272
#[test]
@@ -236,6 +281,14 @@ fn api_all_non_error_types_have_non_empty_debug() {
236281

237282
let debug = format!("{:?}", t.a.a);
238283
assert!(!debug.is_empty());
284+
let debug = format!("{:?}", t.a.b);
285+
assert!(!debug.is_empty());
286+
let debug = format!("{:?}", t.a.c);
287+
assert!(!debug.is_empty());
288+
let debug = format!("{:?}", t.a.d);
289+
assert!(!debug.is_empty());
290+
let debug = format!("{:?}", t.a.e);
291+
assert!(!debug.is_empty());
239292

240293
let debug = format!("{:?}", t.b.a);
241294
assert!(!debug.is_empty());
@@ -261,6 +314,12 @@ fn api_all_non_error_types_have_non_empty_debug() {
261314
assert!(!debug.is_empty());
262315
let debug = format!("{:?}", t.b.l);
263316
assert!(!debug.is_empty());
317+
let debug = format!("{:?}", t.b.m);
318+
assert!(!debug.is_empty());
319+
let debug = format!("{:?}", t.b.n);
320+
assert!(!debug.is_empty());
321+
let debug = format!("{:?}", t.b.o);
322+
assert!(!debug.is_empty());
264323
}
265324

266325
#[test]
@@ -287,6 +346,7 @@ fn regression_default() {
287346
d: BlockMtpInterval::ZERO,
288347
e: relative::NumberOf512Seconds::ZERO,
289348
f: relative::NumberOfBlocks::ZERO,
349+
g: Sequence::MAX,
290350
};
291351
assert_eq!(got, want);
292352
}
@@ -327,8 +387,9 @@ impl<'a> Arbitrary<'a> for Structs {
327387
j: absolute::MedianTimePast::arbitrary(u)?,
328388
k: relative::NumberOf512Seconds::arbitrary(u)?,
329389
l: relative::NumberOfBlocks::arbitrary(u)?,
330-
m: BlockTime::arbitrary(u)?,
331-
n: Weight::arbitrary(u)?,
390+
m: sequence::Sequence::arbitrary(u)?,
391+
n: BlockTime::arbitrary(u)?,
392+
o: Weight::arbitrary(u)?,
332393
};
333394
Ok(a)
334395
}
@@ -339,8 +400,10 @@ impl<'a> Arbitrary<'a> for Enums {
339400
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
340401
let a = Self {
341402
a: amount::Denomination::arbitrary(u)?,
342-
b: NumOpResult::<Amount>::arbitrary(u)?,
343-
c: result::MathOp::arbitrary(u)?,
403+
b: absolute::LockTime::arbitrary(u)?,
404+
c: relative::LockTime::arbitrary(u)?,
405+
d: result::MathOp::arbitrary(u)?,
406+
e: result::NumOpResult::<Amount>::arbitrary(u)?,
344407
};
345408
Ok(a)
346409
}

0 commit comments

Comments
 (0)