light: tests for response module

This commit is contained in:
Robert Habermeier 2016-12-14 20:27:03 +01:00
parent 887bcfb88a
commit 0d466fa8d0

View File

@ -21,10 +21,10 @@ use std::fmt;
use ethcore::header::Header; use ethcore::header::Header;
use light::request::{HashOrNumber, Headers as HeadersRequest}; use light::request::{HashOrNumber, Headers as HeadersRequest};
use rlp::{DecoderError, UntrustedRlp, View}; use rlp::{DecoderError, UntrustedRlp, View};
use util::H256; use util::{Bytes, H256};
/// Errors found when decoding headers and verifying with basic constraints. /// Errors found when decoding headers and verifying with basic constraints.
#[derive(Debug, Clone)] #[derive(Debug, PartialEq)]
pub enum BasicError { pub enum BasicError {
/// Wrong skip value: expected, found (if any). /// Wrong skip value: expected, found (if any).
WrongSkip(u64, Option<u64>), WrongSkip(u64, Option<u64>),
@ -46,7 +46,7 @@ impl From<DecoderError> for BasicError {
impl fmt::Display for BasicError { impl fmt::Display for BasicError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Header response verification error: "); try!(write!(f, "Header response verification error: "));
match *self { match *self {
BasicError::WrongSkip(ref exp, ref got) BasicError::WrongSkip(ref exp, ref got)
@ -58,7 +58,7 @@ impl fmt::Display for BasicError {
BasicError::TooManyHeaders(ref max, ref got) BasicError::TooManyHeaders(ref max, ref got)
=> write!(f, "too many headers (max {}, got {})", max, got), => write!(f, "too many headers (max {}, got {})", max, got),
BasicError::Decoder(ref err) BasicError::Decoder(ref err)
=> write!(f, "invalid encoding ({})", err), => write!(f, "{}", err),
} }
} }
} }
@ -73,7 +73,7 @@ pub trait Constraint {
/// Decode a response and do basic verification against a request. /// Decode a response and do basic verification against a request.
pub fn decode_and_verify(headers: &[Bytes], request: &HeadersRequest) -> Result<Vec<Header>, BasicError> { pub fn decode_and_verify(headers: &[Bytes], request: &HeadersRequest) -> Result<Vec<Header>, BasicError> {
let headers: Vec<_> = try!!(headers.iter().map(|x| UntrustedRlp::new(&x).as_val()).collect()); let headers: Vec<_> = try!(headers.iter().map(|x| UntrustedRlp::new(&x).as_val()).collect());
let reverse = request.reverse; let reverse = request.reverse;
@ -84,6 +84,8 @@ pub fn decode_and_verify(headers: &[Bytes], request: &HeadersRequest) -> Result<
} }
try!(SkipsBetween(request.skip).verify(&headers, reverse)); try!(SkipsBetween(request.skip).verify(&headers, reverse));
Ok(headers)
} }
struct StartsAtNumber(u64); struct StartsAtNumber(u64);
@ -150,3 +152,107 @@ impl Constraint for Max {
} }
} }
#[cfg(test)]
mod tests {
use ethcore::header::Header;
use light::request::Headers as HeadersRequest;
use super::*;
#[test]
fn sequential_forward() {
let request = HeadersRequest {
start: 10.into(),
max: 30,
skip: 0,
reverse: false,
};
let mut parent_hash = None;
let headers: Vec<_> = (0..25).map(|x| x + 10).map(|x| {
let mut header = Header::default();
header.set_number(x);
if let Some(parent_hash) = parent_hash {
header.set_parent_hash(parent_hash);
}
parent_hash = Some(header.hash());
::rlp::encode(&header).to_vec()
}).collect();
assert!(decode_and_verify(&headers, &request).is_ok());
}
#[test]
fn sequential_backward() {
let request = HeadersRequest {
start: 10.into(),
max: 30,
skip: 0,
reverse: true,
};
let mut parent_hash = None;
let headers: Vec<_> = (0..25).map(|x| x + 10).rev().map(|x| {
let mut header = Header::default();
header.set_number(x);
if let Some(parent_hash) = parent_hash {
header.set_parent_hash(parent_hash);
}
parent_hash = Some(header.hash());
::rlp::encode(&header).to_vec()
}).collect();
assert!(decode_and_verify(&headers, &request).is_ok());
}
#[test]
fn too_many() {
let request = HeadersRequest {
start: 10.into(),
max: 20,
skip: 0,
reverse: false,
};
let mut parent_hash = None;
let headers: Vec<_> = (0..25).map(|x| x + 10).map(|x| {
let mut header = Header::default();
header.set_number(x);
if let Some(parent_hash) = parent_hash {
header.set_parent_hash(parent_hash);
}
parent_hash = Some(header.hash());
::rlp::encode(&header).to_vec()
}).collect();
assert_eq!(decode_and_verify(&headers, &request), Err(BasicError::TooManyHeaders(20, 25)));
}
#[test]
fn wrong_skip() {
let request = HeadersRequest {
start: 10.into(),
max: 30,
skip: 5,
reverse: false,
};
let headers: Vec<_> = (0..25).map(|x| x * 3).map(|x| x + 10).map(|x| {
let mut header = Header::default();
header.set_number(x);
::rlp::encode(&header).to_vec()
}).collect();
assert_eq!(decode_and_verify(&headers, &request), Err(BasicError::WrongSkip(5, Some(2))));
}
}