Skip to content

Commit c34d88b

Browse files
committed
more tests
1 parent 7ea25c5 commit c34d88b

File tree

5 files changed

+84
-12
lines changed

5 files changed

+84
-12
lines changed

git-protocol/src/packet_line/decode.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ quick_error! {
2222
}
2323
}
2424

25+
#[derive(Debug, Clone)]
2526
pub enum Stream<'a> {
2627
Complete {
2728
line: packet_line::Borrowed<'a>,
2829
bytes_consumed: usize,
2930
},
3031
Incomplete {
32+
/// The amount of additional bytes needed for the parsing to complete
3133
bytes_needed: usize,
3234
},
3335
}
@@ -50,18 +52,26 @@ pub fn streaming(data: &[u8]) -> Result<Stream, Error> {
5052
let mut buf = [0u8; U16_HEX_BYTES / 2];
5153
hex::decode_to_slice(hex_bytes, &mut buf)?;
5254
let wanted_bytes = u16::from_be_bytes(buf) as usize;
55+
if wanted_bytes > MAX_LINE_LEN {
56+
return Err(Error::DataLengthLimitExceeded(wanted_bytes));
57+
}
5358
if data_len < wanted_bytes {
5459
return Ok(Stream::Incomplete {
55-
bytes_needed: wanted_bytes,
60+
bytes_needed: wanted_bytes - data_len,
5661
});
5762
}
58-
if wanted_bytes > MAX_LINE_LEN {
59-
return Err(Error::DataLengthLimitExceeded(wanted_bytes));
63+
64+
if wanted_bytes == 4 {
65+
return Err(Error::DataIsEmpty);
6066
}
6167

6268
// todo: error line
69+
let mut data = &data[U16_HEX_BYTES..wanted_bytes];
70+
if data[data.len() - 1] == b'\n' {
71+
data = &data[..data.len() - 1];
72+
}
6373
Ok(Stream::Complete {
64-
line: packet_line::Borrowed::Data(&data[U16_HEX_BYTES..wanted_bytes]),
74+
line: packet_line::Borrowed::Data(data),
6575
bytes_consumed: wanted_bytes,
6676
})
6777
}

git-protocol/src/packet_line/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use bstr::BStr;
12
use std::io;
23

34
pub(crate) const U16_HEX_BYTES: usize = 4;
@@ -26,6 +27,9 @@ impl<'a> Borrowed<'a> {
2627
Borrowed::Flush => &[],
2728
}
2829
}
30+
pub fn as_bstr(&self) -> &BStr {
31+
self.as_slice().into()
32+
}
2933
}
3034

3135
pub mod decode;

git-protocol/tests/packet_line/decode.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod streaming {
2+
use crate::packet_line::assert_err_display;
23
use git_protocol::{
34
packet_line::decode::{self, streaming, Stream},
45
PacketLine,
@@ -12,7 +13,7 @@ mod streaming {
1213
match res? {
1314
Stream::Complete { line, bytes_consumed } => {
1415
assert_eq!(bytes_consumed, expected_consumed);
15-
assert_eq!(line, expected_value);
16+
assert_eq!(line.as_bstr(), expected_value.as_bstr());
1617
}
1718
Stream::Incomplete { .. } => panic!("expected parsing to be complete, not partial"),
1819
}
@@ -24,6 +25,32 @@ mod streaming {
2425
assert_complete(streaming(b"0000someotherstuff"), 4, PacketLine::Flush)
2526
}
2627

28+
#[test]
29+
fn trailing_line_feeds_are_removed() -> crate::Result {
30+
assert_complete(streaming(b"0006a\n"), 6, PacketLine::Data(b"a"))
31+
}
32+
33+
#[test]
34+
fn error_on_oversized_line() {
35+
assert_err_display(
36+
streaming(b"ffff"),
37+
"The data received claims to be larger than than the maximum allowed size: got 65535, exceeds 65516",
38+
);
39+
}
40+
41+
#[test]
42+
fn error_on_invalid_hex() {
43+
assert_err_display(
44+
streaming(b"fooo"),
45+
"Failed to decode the first four hex bytes indicating the line length",
46+
);
47+
}
48+
49+
#[test]
50+
fn error_on_empty_line() {
51+
assert_err_display(streaming(b"0004"), "Received an invalid empty line");
52+
}
53+
2754
#[test]
2855
fn round_trips() -> crate::Result {
2956
for (line, bytes) in &[(PacketLine::Flush, 4), (PacketLine::Data(b"hello there"), 15)] {
@@ -33,4 +60,34 @@ mod streaming {
3360
}
3461
Ok(())
3562
}
63+
64+
mod incomplete {
65+
use git_protocol::packet_line::decode::{self, streaming, Stream};
66+
67+
fn assert_incomplete(res: Result<Stream, decode::Error>, expected_missing: usize) -> crate::Result {
68+
match res? {
69+
Stream::Complete { .. } => {
70+
panic!("expected parsing to be partial, not complete");
71+
}
72+
Stream::Incomplete { bytes_needed } => {
73+
assert_eq!(bytes_needed, expected_missing);
74+
}
75+
}
76+
Ok(())
77+
}
78+
79+
#[test]
80+
fn missing_hex_bytes() -> crate::Result {
81+
assert_incomplete(streaming(b"0"), 3)?;
82+
assert_incomplete(streaming(b"00"), 2)?;
83+
Ok(())
84+
}
85+
86+
#[test]
87+
fn missing_data_bytes() -> crate::Result {
88+
assert_incomplete(streaming(b"0005"), 1)?;
89+
assert_incomplete(streaming(b"0006a"), 1)?;
90+
Ok(())
91+
}
92+
}
3693
}

git-protocol/tests/packet_line/encode.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod data_to_write {
2+
use crate::packet_line::assert_err_display;
23
use bstr::ByteSlice;
34
use git_protocol::packet_line::encode::{data_to_write, flush_to_write};
45
use std::io;
@@ -9,13 +10,6 @@ mod data_to_write {
910
v
1011
}
1112

12-
fn assert_err_display<T, E: std::error::Error>(res: Result<T, E>, expected: impl AsRef<str>) {
13-
match res {
14-
Ok(_) => assert!(false, "Expected error '{}', got value", expected.as_ref()),
15-
Err(err) => assert_eq!(err.to_string(), expected.as_ref()),
16-
}
17-
}
18-
1913
#[test]
2014
fn success_binary_and_non_binary() -> crate::Result {
2115
let mut out = Vec::new();

git-protocol/tests/packet_line/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
1+
fn assert_err_display<T: std::fmt::Debug, E: std::error::Error>(res: Result<T, E>, expected: impl AsRef<str>) {
2+
match res {
3+
Ok(v) => assert!(false, "Expected error '{}', got value {:?}", expected.as_ref(), v),
4+
Err(err) => assert_eq!(err.to_string(), expected.as_ref()),
5+
}
6+
}
7+
18
mod decode;
29
mod encode;

0 commit comments

Comments
 (0)