Skip to content

Commit

Permalink
Refactor test API (#82)
Browse files Browse the repository at this point in the history
  • Loading branch information
terror authored Feb 1, 2022
1 parent 131fb13 commit 460d670
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 41 deletions.
4 changes: 4 additions & 0 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,17 +258,21 @@ impl Index {
let rtx = self.database.begin_read()?;
let outpoint_to_ordinal_ranges: ReadOnlyTable<[u8], [u8]> =
rtx.open_table(Self::OUTPOINT_TO_ORDINAL_RANGES)?;

let mut key = Vec::new();
outpoint.consensus_encode(&mut key)?;

let ordinal_ranges = outpoint_to_ordinal_ranges
.get(key.as_slice())?
.ok_or("Could not find outpoint in index")?;

let mut output = Vec::new();
for chunk in ordinal_ranges.to_value().chunks_exact(16) {
let start = u64::from_le_bytes(chunk[0..8].try_into().unwrap());
let end = u64::from_le_bytes(chunk[8..16].try_into().unwrap());
output.push((start, end));
}

Ok(output)
}
}
18 changes: 16 additions & 2 deletions tests/find.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ fn first_satoshi() -> Result {
Test::new()?
.command("find --blocksdir blocks 0 --as-of-height 0")
.expected_stdout("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0:0\n")
.block()
.run()
}

Expand All @@ -13,6 +14,7 @@ fn first_satoshi_slot() -> Result {
Test::new()?
.command("find --blocksdir blocks 0 --as-of-height 0 --slot")
.expected_stdout("0.0.0.0\n")
.block()
.run()
}

Expand All @@ -21,6 +23,7 @@ fn second_satoshi() -> Result {
Test::new()?
.command("find --blocksdir blocks 1 --as-of-height 0")
.expected_stdout("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0:1\n")
.block()
.run()
}

Expand All @@ -29,14 +32,17 @@ fn second_satoshi_slot() -> Result {
Test::new()?
.command("find --blocksdir blocks 1 --as-of-height 0 --slot")
.expected_stdout("0.0.0.1\n")
.block()
.run()
}

#[test]
fn first_satoshi_of_second_block() -> Result {
Test::new()?
.command("find --blocksdir blocks 5000000000 --as-of-height 1")
.expected_stdout("e5fb252959bdc7727c80296dbc53e1583121503bb2e266a609ebc49cf2a74c1d:0:0\n")
.expected_stdout("9068a11b8769174363376b606af9a4b8b29dd7b13d013f4b0cbbd457db3c3ce5:0:0\n")
.block()
.block()
.run()
}

Expand All @@ -45,14 +51,19 @@ fn first_satoshi_of_second_block_slot() -> Result {
Test::new()?
.command("find --blocksdir blocks 5000000000 --as-of-height 1 --slot")
.expected_stdout("1.0.0.0\n")
.block()
.block()
.run()
}

#[test]
fn first_satoshi_spent_in_second_block() -> Result {
Test::new()?
.command("find --blocksdir blocks 0 --as-of-height 1")
.expected_stdout("1e8149c3be0dd66b1cbcb4652d15bea04a9bc8d515c4f544e71bb35a9cba1ed0:0:0\n")
.expected_stdout("72e60639a1dcc6263ed214a1db0dc9545bf65d9327e5a60e84bd3db7fbb4c2fa:0:0\n")
.block()
.block()
.transaction(&[(0, 0, 0)], 1)
.run()
}

Expand All @@ -61,5 +72,8 @@ fn first_satoshi_spent_in_second_block_slot() -> Result {
Test::new()?
.command("find --blocksdir blocks 0 --as-of-height 1 --slot")
.expected_stdout("1.1.0.0\n")
.block()
.block()
.transaction(&[(0, 0, 0)], 1)
.run()
}
104 changes: 66 additions & 38 deletions tests/integration.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use {
bitcoin::{
blockdata::constants::{genesis_block, COIN_VALUE, MAX_SEQUENCE},
blockdata::constants::{genesis_block, COIN_VALUE},
blockdata::script,
consensus::Encodable,
{Block, BlockHeader, Network, OutPoint, Transaction, TxIn, TxOut},
Expand Down Expand Up @@ -35,6 +35,7 @@ struct Test {
expected_status: i32,
ignore_stdout: bool,
tempdir: TempDir,
blocks: Vec<Block>,
}

impl Test {
Expand All @@ -46,6 +47,7 @@ impl Test {
expected_status: 0,
ignore_stdout: false,
tempdir: TempDir::new()?,
blocks: Vec::new(),
})
}

Expand Down Expand Up @@ -124,63 +126,89 @@ impl Test {
Ok(stdout.to_owned())
}

fn populate_blocksdir(&self) -> io::Result<()> {
let mut blocks = vec![genesis_block(Network::Bitcoin)];

blocks.push(Block {
header: BlockHeader {
version: 0,
prev_blockhash: blocks.last().unwrap().block_hash(),
merkle_root: Default::default(),
time: 0,
bits: 0,
nonce: 0,
},
txdata: vec![
Transaction {
version: 1,
lock_time: 0,
input: vec![TxIn {
previous_output: OutPoint::null(),
script_sig: script::Builder::new().push_scriptint(1).into_script(),
sequence: MAX_SEQUENCE,
witness: vec![],
}],
output: vec![TxOut {
value: 50 * COIN_VALUE,
script_pubkey: script::Builder::new().into_script(),
}],
fn block(mut self) -> Self {
if self.blocks.is_empty() {
self.blocks.push(genesis_block(Network::Bitcoin));
} else {
self.blocks.push(Block {
header: BlockHeader {
version: 0,
prev_blockhash: self.blocks.last().unwrap().block_hash(),
merkle_root: Default::default(),
time: 0,
bits: 0,
nonce: 0,
},
Transaction {
version: 1,
txdata: vec![Transaction {
version: 0,
lock_time: 0,
input: vec![TxIn {
script_sig: script::Builder::new().into_script(),
sequence: MAX_SEQUENCE,
previous_output: OutPoint::null(),
script_sig: script::Builder::new()
.push_scriptint(self.blocks.len().try_into().unwrap())
.into_script(),
sequence: 0,
witness: vec![],
previous_output: OutPoint {
txid: blocks.last().unwrap().txdata[0].txid(),
vout: 0,
},
}],
output: vec![TxOut {
value: 50 * COIN_VALUE,
script_pubkey: script::Builder::new().into_script(),
}],
},
}],
});
}
self
}

fn transaction(mut self, slots: &[(usize, usize, u32)], output_count: u64) -> Self {
let value = slots
.iter()
.map(|slot| self.blocks[slot.0].txdata[slot.1].output[slot.2 as usize].value)
.sum::<u64>();

let tx = Transaction {
version: 0,
lock_time: 0,
input: slots
.iter()
.map(|slot| TxIn {
previous_output: OutPoint {
txid: self.blocks[slot.0].txdata[slot.1].txid(),
vout: slot.2,
},
script_sig: script::Builder::new().into_script(),
sequence: 0,
witness: vec![],
})
.collect(),
output: vec![
TxOut {
value: value / output_count,
script_pubkey: script::Builder::new().into_script(),
};
output_count.try_into().unwrap()
],
});
};

self.blocks.last_mut().unwrap().txdata.push(tx);

self
}

fn populate_blocksdir(&self) -> io::Result<()> {
let blocksdir = self.tempdir.path().join("blocks");
fs::create_dir(&blocksdir)?;
let mut blockfile = File::create(blocksdir.join("blk00000.dat"))?;

for block in blocks {
for block in &self.blocks {
let mut encoded = Vec::new();
block.consensus_encode(&mut encoded)?;
blockfile.write_all(&[0xf9, 0xbe, 0xb4, 0xd9])?;
blockfile.write_all(&(encoded.len() as u32).to_le_bytes())?;
blockfile.write_all(&encoded)?;
for tx in &block.txdata {
eprintln!("{}", tx.txid());
}
}

Ok(())
Expand Down
56 changes: 55 additions & 1 deletion tests/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ fn first_coinbase_transaction() -> Result {
.command(
"list --blocksdir blocks 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0",
)
.block()
.expected_stdout("[0,5000000000)\n")
.run()
}
Expand All @@ -14,8 +15,61 @@ fn first_coinbase_transaction() -> Result {
fn second_coinbase_transaction() -> Result {
Test::new()?
.command(
"list --blocksdir blocks e5fb252959bdc7727c80296dbc53e1583121503bb2e266a609ebc49cf2a74c1d:0",
"list --blocksdir blocks 9068a11b8769174363376b606af9a4b8b29dd7b13d013f4b0cbbd457db3c3ce5:0",
)
.block()
.block()
.expected_stdout("[5000000000,10000000000)\n")
.run()
}

#[test]
fn third_coinbase_transaction_is_not_duplicate() -> Result {
Test::new()?
.command(
"list --blocksdir blocks 8aa5103b13b5b233ac417ee31f21820c9284af2b7a2080a142c2d20e1697b0f4:0",
)
.block()
.block()
.block()
.expected_stdout("[10000000000,15000000000)\n")
.run()
}

#[test]
fn split_ranges_are_tracked_correctly() -> Result {
Test::new()?
.command(
"list --blocksdir blocks 7ab338c0e46c95c119ba8ff0a3f6cf64f56f35ba5553a399fdd38169cca00be3:0",
)
.block()
.block()
.transaction(&[(0, 0, 0)], 2)
.expected_stdout("[0,2500000000)\n")
.run()?;

Test::new()?
.command(
"list --blocksdir blocks 7ab338c0e46c95c119ba8ff0a3f6cf64f56f35ba5553a399fdd38169cca00be3:1",
)
.block()
.block()
.transaction(&[(0, 0, 0)], 2)
.expected_stdout("[2500000000,5000000000)\n")
.run()
}

#[test]
fn merge_ranges_are_tracked_correctly() -> Result {
Test::new()?
.command(
"list --blocksdir blocks fe283c08e46269a7bbe36b629bc2be55d604152419818e94330477c9c3487eec:0",
)
.block()
.block()
.transaction(&[(0, 0, 0)], 2)
.block()
.transaction(&[(1, 1, 0), (1, 1, 1)], 1)
.expected_stdout("[0,2500000000)\n[2500000000,5000000000)\n")
.run()
}

0 comments on commit 460d670

Please sign in to comment.