Skip to content

Commit

Permalink
Merge rust-bitcoin#4033: primitives: Add tests to transaction
Browse files Browse the repository at this point in the history
435750f Add a parse_vout test (Jamil Lambert, PhD)
957be3c Add OutPoint test (Jamil Lambert, PhD)
a4ef027 Add tests of transaction functions (Jamil Lambert, PhD)

Pull request description:

  Add tests to kill the mutants in `primitives/src/transaction.rs`

ACKs for top commit:
  tcharding:
    ACK 435750f

Tree-SHA512: 78baf40ad6ed1cd5b3a33346b4702c3a7efbb03ae6eec9a802d3dea99910373cf4e8053c73e9fdc02ce54852d3ee43253f2ff0c149c86870ecfed2fc909e5bcf
  • Loading branch information
apoelstra committed Feb 13, 2025
2 parents 20e970d + 435750f commit 7a369ae
Showing 1 changed file with 80 additions and 0 deletions.
80 changes: 80 additions & 0 deletions primitives/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,3 +598,83 @@ impl<'a> Arbitrary<'a> for Txid {
Ok(Txid(t))
}
}

#[cfg(feature = "alloc")]
#[cfg(test)]
mod tests {
use super::*;

#[test]
fn transaction_functions() {
let txin = TxIn {
previous_output: OutPoint {
txid: Txid::from_byte_array([0xAA; 32]), // Arbitrary invalid dummy value.
vout: 0,
},
script_sig: ScriptBuf::new(),
sequence: Sequence::MAX,
witness: Witness::new(),
};

let txout = TxOut {
value: Amount::from_sat(123456789),
script_pubkey: ScriptBuf::new(),
};

let tx_orig = Transaction {
version: Version::ONE,
lock_time: absolute::LockTime::from_consensus(1738968231), // The time this was written
input: vec![txin.clone()],
output: vec![txout.clone()],
};

// Test changing the transaction
let mut tx = tx_orig.clone();
tx.inputs_mut()[0].previous_output.txid = Txid::from_byte_array([0xFF; 32]);
tx.outputs_mut()[0].value = Amount::from_sat(987654321);
assert_eq!(tx.inputs()[0].previous_output.txid.to_byte_array(), [0xFF; 32]);
assert_eq!(tx.outputs()[0].value.to_sat(), 987654321);

// Test uses_segwit_serialization
assert!(!tx.uses_segwit_serialization());
tx.input[0].witness.push(vec![0xAB, 0xCD, 0xEF]);
assert!(tx.uses_segwit_serialization());

// Test partial ord
assert!(tx > tx_orig);
}

#[test]
fn outpoint_from_str() {
// Check format errors
let mut outpoint_str = "0".repeat(64); // No ":"
let outpoint: Result<OutPoint, ParseOutPointError> = outpoint_str.parse();
assert_eq!(outpoint, Err(ParseOutPointError::Format));

outpoint_str.push(':'); // Empty vout
let outpoint: Result<OutPoint, ParseOutPointError> = outpoint_str.parse();
assert_eq!(outpoint, Err(ParseOutPointError::Format));

outpoint_str.push('0'); // Correct format
let outpoint: OutPoint = outpoint_str.parse().unwrap();
assert_eq!(outpoint.txid, Txid::from_byte_array([0; 32]));
assert_eq!(outpoint.vout, 0);

// Check the number of bytes OutPoint contributes to the transaction is equal to SIZE
let outpoint_size = outpoint.txid.as_byte_array().len() + outpoint.vout.to_le_bytes().len();
assert_eq!(outpoint_size, OutPoint::SIZE);

// Check TooLong error
outpoint_str.push_str("0000000000");
let outpoint: Result<OutPoint, ParseOutPointError> = outpoint_str.parse();
assert_eq!(outpoint, Err(ParseOutPointError::TooLong));
}

#[test]
fn canonical_vout() {
assert_eq!(parse_vout("0").unwrap(), 0);
assert_eq!(parse_vout("1").unwrap(), 1);
assert!(parse_vout("01").is_err()); // Leading zero not allowed
assert!(parse_vout("+1").is_err()); // Non digits not allowed
}
}

0 comments on commit 7a369ae

Please sign in to comment.