Skip to content

Commit 40baea5

Browse files
committed
test: add tests for RawRecordIterator
- Added tests for valid record parsing, empty streams, and parser behavior with invalid headers. - Enhanced coverage for io errors and parse error handling with `core_dump` toggle.
1 parent a9c5496 commit 40baea5

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

tests/raw_iter.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
use std::io::Cursor;
2+
3+
use bgpkit_parser::models::{CommonHeader, EntryType};
4+
use bgpkit_parser::BgpkitParser;
5+
6+
fn build_valid_bgp4mp_zero_len_record() -> Vec<u8> {
7+
let hdr = CommonHeader {
8+
timestamp: 1,
9+
microsecond_timestamp: None,
10+
entry_type: EntryType::BGP4MP,
11+
entry_subtype: 0,
12+
length: 0,
13+
};
14+
hdr.encode().to_vec()
15+
}
16+
17+
fn build_bgp4mp_with_len(len: u32) -> Vec<u8> {
18+
let hdr = CommonHeader {
19+
timestamp: 2,
20+
microsecond_timestamp: None,
21+
entry_type: EntryType::BGP4MP,
22+
entry_subtype: 0,
23+
length: len,
24+
};
25+
let mut bytes = hdr.encode().to_vec();
26+
bytes.extend(std::iter::repeat(0u8).take(len as usize));
27+
bytes
28+
}
29+
30+
fn build_invalid_entry_type_header() -> Vec<u8> {
31+
// Manually craft a header with an undefined EntryType (e.g., 15)
32+
let mut bytes = Vec::new();
33+
bytes.extend(0u32.to_be_bytes()); // timestamp
34+
bytes.extend(15u16.to_be_bytes()); // invalid entry type (not defined)
35+
bytes.extend(0u16.to_be_bytes()); // subtype
36+
bytes.extend(0u32.to_be_bytes()); // length
37+
bytes
38+
}
39+
40+
#[test]
41+
fn test_raw_record_iterator_yields_valid_record() {
42+
let mut data = Vec::new();
43+
data.extend(build_valid_bgp4mp_zero_len_record());
44+
45+
let cursor = Cursor::new(data);
46+
let parser = BgpkitParser::from_reader(cursor);
47+
let mut iter = parser.into_raw_record_iter();
48+
49+
let rec = iter.next().expect("should yield one record");
50+
assert_eq!(rec.common_header.entry_type, EntryType::BGP4MP);
51+
assert_eq!(rec.common_header.length, 0);
52+
assert_eq!(rec.raw_bytes.len(), 0);
53+
54+
// then end of stream
55+
assert!(iter.next().is_none());
56+
}
57+
58+
#[test]
59+
fn test_raw_record_iterator_empty_stream_is_eof() {
60+
let cursor = Cursor::new(Vec::<u8>::new());
61+
let parser = BgpkitParser::from_reader(cursor);
62+
let mut iter = parser.into_raw_record_iter();
63+
64+
assert!(iter.next().is_none(), "empty stream should be EOF");
65+
}
66+
67+
#[test]
68+
fn test_raw_record_iterator_parse_error_skips_when_no_core_dump() {
69+
// Stream: [invalid header][valid record]
70+
let mut data = Vec::new();
71+
data.extend(build_invalid_entry_type_header());
72+
data.extend(build_bgp4mp_with_len(0));
73+
74+
let cursor = Cursor::new(data);
75+
let parser = BgpkitParser::from_reader(cursor); // core_dump=false by default
76+
let mut iter = parser.into_raw_record_iter();
77+
78+
// Iterator should skip the invalid header and yield the valid record
79+
let rec = iter.next().expect("should yield valid record after skipping parse error");
80+
assert_eq!(rec.common_header.entry_type, EntryType::BGP4MP);
81+
assert_eq!(rec.raw_bytes.len(), 0);
82+
assert!(iter.next().is_none());
83+
}
84+
85+
#[test]
86+
fn test_raw_record_iterator_parse_error_stops_when_core_dump_enabled() {
87+
// Stream: [invalid header][valid record]
88+
let mut data = Vec::new();
89+
data.extend(build_invalid_entry_type_header());
90+
data.extend(build_bgp4mp_with_len(0));
91+
92+
let cursor = Cursor::new(data);
93+
let parser = BgpkitParser::from_reader(cursor).enable_core_dump();
94+
let mut iter = parser.into_raw_record_iter();
95+
96+
// Iterator should stop on parse error when core_dump is enabled
97+
assert!(iter.next().is_none());
98+
}
99+
100+
#[test]
101+
fn test_raw_record_iterator_io_error_stops_iteration() {
102+
// Craft a header that declares 5 bytes but only provide 3 -> triggers IoError in chunk_mrt_record
103+
let hdr = CommonHeader {
104+
timestamp: 3,
105+
microsecond_timestamp: None,
106+
entry_type: EntryType::BGP4MP,
107+
entry_subtype: 0,
108+
length: 5,
109+
};
110+
let mut data = hdr.encode().to_vec();
111+
data.extend([0u8; 3]); // insufficient bytes
112+
113+
let cursor = Cursor::new(data);
114+
let parser = BgpkitParser::from_reader(cursor);
115+
let mut iter = parser.into_raw_record_iter();
116+
117+
// On IoError branch, iterator stops and returns None immediately
118+
assert!(iter.next().is_none());
119+
}

0 commit comments

Comments
 (0)