consensus_encoding: move decode inline tests to integration
What changed, and why it matters
This commit simply moves existing unit tests from inside the source file to a separate integration test file. No production code behavior was changed, so there is no security risk or fix.
No action needed; this is a test-only refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff removes the #[cfg(test)] inline test module from consensus_encoding/src/decode/mod.rs and appends the same tests to consensus_encoding/tests/decode.rs. The tests are unchanged in logic and only adjusted for visibility/imports. No library code was modified.
Changed components
consensus_encoding/src/decode/mod.rsconsensus_encoding/tests/decode.rsInspect captured patch +156 / −161
diff --git a/consensus_encoding/src/decode/mod.rs b/consensus_encoding/src/decode/mod.rs
index ed48e829..6156c0d0 100644
--- a/consensus_encoding/src/decode/mod.rs
+++ b/consensus_encoding/src/decode/mod.rs
@@ -256,163 +256,3 @@ where
impl<D> From<std::io::Error> for ReadError<D> {
fn from(e: std::io::Error) -> Self { Self::Io(e) }
}
-
-#[cfg(test)]
-mod tests {
- #[cfg(feature = "std")]
- use alloc::vec::Vec;
- #[cfg(feature = "std")]
- use std::io::{Cursor, Read};
-
- use super::*;
- use crate::decode::decoders::{ArrayDecoder, UnexpectedEofError};
-
- #[derive(Debug, PartialEq)]
- struct TestArray([u8; 4]);
-
- impl Decodable for TestArray {
- type Decoder = TestArrayDecoder;
- fn decoder() -> Self::Decoder { TestArrayDecoder { inner: ArrayDecoder::new() } }
- }
-
- struct TestArrayDecoder {
- inner: ArrayDecoder<4>,
- }
-
- impl Decoder for TestArrayDecoder {
- type Output = TestArray;
- type Error = UnexpectedEofError;
-
- fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
- self.inner.push_bytes(bytes)
- }
-
- fn end(self) -> Result<Self::Output, Self::Error> { self.inner.end().map(TestArray) }
-
- fn read_limit(&self) -> usize { self.inner.read_limit() }
- }
-
- #[test]
- fn decode_from_slice_success() {
- let data = [1, 2, 3, 4];
- let result: Result<TestArray, _> = decode_from_slice(&data);
- assert!(result.is_ok());
- let decoded = result.unwrap();
- assert_eq!(decoded.0, [1, 2, 3, 4]);
- }
-
- #[test]
- fn decode_from_slice_unexpected_eof() {
- let data = [1, 2, 3];
- let result: Result<TestArray, _> = decode_from_slice(&data);
- assert!(result.is_err());
- }
-
- #[test]
- fn decode_from_slice_extra_data() {
- let data = [1, 2, 3, 4, 5];
- let result: Result<TestArray, _> = decode_from_slice(&data);
- assert!(result.is_ok());
- let decoded = result.unwrap();
- assert_eq!(decoded.0, [1, 2, 3, 4]);
- }
-
- #[test]
- #[cfg(feature = "std")]
- fn decode_from_read_extra_data() {
- let data = [1, 2, 3, 4, 5, 6];
- let mut cursor = Cursor::new(&data);
- let result: Result<TestArray, _> = decode_from_read(&mut cursor);
- assert!(result.is_ok());
- let decoded = result.unwrap();
- assert_eq!(decoded.0, [1, 2, 3, 4]);
- }
-
- #[test]
- #[cfg(feature = "std")]
- fn decode_from_read_success() {
- let data = [1, 2, 3, 4];
- let cursor = Cursor::new(&data);
- let result: Result<TestArray, _> = decode_from_read(cursor);
- assert!(result.is_ok());
- let decoded = result.unwrap();
- assert_eq!(decoded.0, [1, 2, 3, 4]);
- }
-
- #[test]
- #[cfg(feature = "std")]
- fn decode_from_read_unexpected_eof() {
- let data = [1, 2, 3];
- let cursor = Cursor::new(&data);
- let result: Result<TestArray, _> = decode_from_read(cursor);
- assert!(matches!(result, Err(ReadError::Decode(_))));
- }
-
- #[test]
- #[cfg(feature = "std")]
- fn decode_from_read_trait_object() {
- let data = [1, 2, 3, 4];
- let mut cursor = Cursor::new(&data);
- // Test that we can pass a trait object (&mut dyn BufRead implements BufRead).
- let reader: &mut dyn std::io::BufRead = &mut cursor;
- let result: Result<TestArray, _> = decode_from_read(reader);
- assert!(result.is_ok());
- let decoded = result.unwrap();
- assert_eq!(decoded.0, [1, 2, 3, 4]);
- }
-
- #[test]
- #[cfg(feature = "std")]
- fn decode_from_read_by_reference() {
- let data = [1, 2, 3, 4];
- let mut cursor = Cursor::new(&data);
- // Test that we can pass by reference (&mut T implements BufRead when T: BufRead).
- let result: Result<TestArray, _> = decode_from_read(&mut cursor);
- assert!(result.is_ok());
- let decoded = result.unwrap();
- assert_eq!(decoded.0, [1, 2, 3, 4]);
-
- let mut buf = Vec::new();
- let _ = cursor.read_to_end(&mut buf);
- }
-
- #[test]
- #[cfg(feature = "std")]
- fn decode_from_read_unbuffered_success() {
- let data = [1, 2, 3, 4];
- let cursor = Cursor::new(&data);
- let result: Result<TestArray, _> = decode_from_read_unbuffered(cursor);
- assert!(result.is_ok());
- let decoded = result.unwrap();
- assert_eq!(decoded.0, [1, 2, 3, 4]);
- }
-
- #[test]
- #[cfg(feature = "std")]
- fn decode_from_read_unbuffered_unexpected_eof() {
- let data = [1, 2, 3];
- let cursor = Cursor::new(&data);
- let result: Result<TestArray, _> = decode_from_read_unbuffered(cursor);
- assert!(matches!(result, Err(ReadError::Decode(_))));
- }
-
- #[test]
- #[cfg(feature = "std")]
- fn decode_from_read_unbuffered_empty() {
- let data = [];
- let cursor = Cursor::new(&data);
- let result: Result<TestArray, _> = decode_from_read_unbuffered(cursor);
- assert!(matches!(result, Err(ReadError::Decode(_))));
- }
-
- #[test]
- #[cfg(feature = "std")]
- fn decode_from_read_unbuffered_extra_data() {
- let data = [1, 2, 3, 4, 5, 6];
- let cursor = Cursor::new(&data);
- let result: Result<TestArray, _> = decode_from_read_unbuffered(cursor);
- assert!(result.is_ok());
- let decoded = result.unwrap();
- assert_eq!(decoded.0, [1, 2, 3, 4]);
- }
-}
diff --git a/consensus_encoding/tests/decode.rs b/consensus_encoding/tests/decode.rs
index 32670e27..1161d155 100644
--- a/consensus_encoding/tests/decode.rs
+++ b/consensus_encoding/tests/decode.rs
@@ -2,9 +2,15 @@
//! Integration tests for decode module.
+#[cfg(feature = "std")]
+use std::io::{Cursor, Read};
+
use bitcoin_consensus_encoding::{
- ArrayDecoder, CompactSizeDecoder, Decoder, Decoder2, UnexpectedEofError,
+ ArrayDecoder, CompactSizeDecoder, Decodable, Decoder, Decoder2, UnexpectedEofError,
};
+#[cfg(feature = "std")]
+use bitcoin_consensus_encoding::{decode_from_read, decode_from_read_unbuffered, ReadError};
+use bitcoin_consensus_encoding::decode_from_slice;
const EMPTY: &[u8] = &[];
@@ -217,3 +223,152 @@ fn decode_byte_vec_decoder_does_not_overconsume_on_second_chunk() {
let decoded_vec = decoder.end().unwrap();
assert_eq!(decoded_vec, vec![0xAA, 0xBB, 0xCC, 0xDD]);
}
+
+#[derive(Debug, PartialEq)]
+struct TestArray([u8; 4]);
+
+impl Decodable for TestArray {
+ type Decoder = TestArrayDecoder;
+ fn decoder() -> Self::Decoder { TestArrayDecoder { inner: ArrayDecoder::new() } }
+}
+
+struct TestArrayDecoder {
+ inner: ArrayDecoder<4>,
+}
+
+impl Decoder for TestArrayDecoder {
+ type Output = TestArray;
+ type Error = UnexpectedEofError;
+
+ fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
+ self.inner.push_bytes(bytes)
+ }
+
+ fn end(self) -> Result<Self::Output, Self::Error> { self.inner.end().map(TestArray) }
+
+ fn read_limit(&self) -> usize { self.inner.read_limit() }
+}
+
+#[test]
+fn decode_from_slice_success() {
+ let data = [1, 2, 3, 4];
+ let result: Result<TestArray, _> = decode_from_slice(&data);
+ assert!(result.is_ok());
+ let decoded = result.unwrap();
+ assert_eq!(decoded.0, [1, 2, 3, 4]);
+}
+
+#[test]
+fn decode_from_slice_unexpected_eof() {
+ let data = [1, 2, 3];
+ let result: Result<TestArray, _> = decode_from_slice(&data);
+ assert!(result.is_err());
+}
+
+#[test]
+fn decode_from_slice_extra_data() {
+ let data = [1, 2, 3, 4, 5];
+ let result: Result<TestArray, _> = decode_from_slice(&data);
+ assert!(result.is_ok());
+ let decoded = result.unwrap();
+ assert_eq!(decoded.0, [1, 2, 3, 4]);
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn decode_from_read_extra_data() {
+ let data = [1, 2, 3, 4, 5, 6];
+ let mut cursor = Cursor::new(&data);
+ let result: Result<TestArray, _> = decode_from_read(&mut cursor);
+ assert!(result.is_ok());
+ let decoded = result.unwrap();
+ assert_eq!(decoded.0, [1, 2, 3, 4]);
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn decode_from_read_success() {
+ let data = [1, 2, 3, 4];
+ let cursor = Cursor::new(&data);
+ let result: Result<TestArray, _> = decode_from_read(cursor);
+ assert!(result.is_ok());
+ let decoded = result.unwrap();
+ assert_eq!(decoded.0, [1, 2, 3, 4]);
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn decode_from_read_unexpected_eof() {
+ let data = [1, 2, 3];
+ let cursor = Cursor::new(&data);
+ let result: Result<TestArray, _> = decode_from_read(cursor);
+ assert!(matches!(result, Err(ReadError::Decode(_))));
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn decode_from_read_trait_object() {
+ let data = [1, 2, 3, 4];
+ let mut cursor = Cursor::new(&data);
+ // Test that we can pass a trait object (&mut dyn BufRead implements BufRead).
+ let reader: &mut dyn std::io::BufRead = &mut cursor;
+ let result: Result<TestArray, _> = decode_from_read(reader);
+ assert!(result.is_ok());
+ let decoded = result.unwrap();
+ assert_eq!(decoded.0, [1, 2, 3, 4]);
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn decode_from_read_by_reference() {
+ let data = [1, 2, 3, 4];
+ let mut cursor = Cursor::new(&data);
+ // Test that we can pass by reference (&mut T implements BufRead when T: BufRead).
+ let result: Result<TestArray, _> = decode_from_read(&mut cursor);
+ assert!(result.is_ok());
+ let decoded = result.unwrap();
+ assert_eq!(decoded.0, [1, 2, 3, 4]);
+
+ let mut buf = Vec::new();
+ let _ = cursor.read_to_end(&mut buf);
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn decode_from_read_unbuffered_success() {
+ let data = [1, 2, 3, 4];
+ let cursor = Cursor::new(&data);
+ let result: Result<TestArray, _> = decode_from_read_unbuffered(cursor);
+ assert!(result.is_ok());
+ let decoded = result.unwrap();
+ assert_eq!(decoded.0, [1, 2, 3, 4]);
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn decode_from_read_unbuffered_unexpected_eof() {
+ let data = [1, 2, 3];
+ let cursor = Cursor::new(&data);
+ let result: Result<TestArray, _> = decode_from_read_unbuffered(cursor);
+ assert!(matches!(result, Err(ReadError::Decode(_))));
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn decode_from_read_unbuffered_empty() {
+ let data = [];
+ let cursor = Cursor::new(&data);
+ let result: Result<TestArray, _> = decode_from_read_unbuffered(cursor);
+ assert!(matches!(result, Err(ReadError::Decode(_))));
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn decode_from_read_unbuffered_extra_data() {
+ let data = [1, 2, 3, 4, 5, 6];
+ let cursor = Cursor::new(&data);
+ let result: Result<TestArray, _> = decode_from_read_unbuffered(cursor);
+ assert!(result.is_ok());
+ let decoded = result.unwrap();
+ assert_eq!(decoded.0, [1, 2, 3, 4]);
+}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.