Skip to content

Commit b898c9d

Browse files
committed
increase test coverage
1 parent db73864 commit b898c9d

File tree

3 files changed

+427
-0
lines changed

3 files changed

+427
-0
lines changed

src/parser/bmp/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ mod tests {
130130
ParserBmpError::CorruptedBmpMessage.to_string(),
131131
"Corrupted BMP message"
132132
);
133+
assert_eq!(
134+
ParserBmpError::CorruptedBgpMessage("test".to_string()).to_string(),
135+
"Corrupted BGP message: test"
136+
);
133137
assert_eq!(
134138
ParserBmpError::TruncatedBmpMessage.to_string(),
135139
"Truncated BMP message"

src/parser/bmp/messages/peer_up_notification.rs

Lines changed: 349 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ mod tests {
143143
use super::*;
144144
use bytes::BytesMut;
145145
use std::net::{IpAddr, Ipv4Addr};
146+
use crate::models::capabilities::{BgpCapabilityType, MultiprotocolExtensionsCapability};
146147

147148
#[test]
148149
fn test_parse_peer_up_notification() {
@@ -227,6 +228,11 @@ mod tests {
227228
warnings
228229
}
229230

231+
// Note: These tests verify that the parser handles LocalRib validation correctly.
232+
// The actual warning messages are logged via the `log` crate and would appear
233+
// in production use. For testing purposes, we verify that parsing succeeds
234+
// and the code paths are exercised.
235+
230236
#[test]
231237
fn test_parse_peer_up_notification_no_warnings() {
232238
let warnings = setup_warning_logger();
@@ -448,4 +454,347 @@ mod tests {
448454
assert_eq!(peer_notification.tlvs[1].info_type, PeerUpTlvType::String);
449455
assert_eq!(peer_notification.tlvs[1].info_value, "Router");
450456
}
457+
458+
#[test]
459+
fn test_local_rib_without_multiprotocol_capability() {
460+
// This test verifies that LocalRib peer up notifications without multiprotocol
461+
// capabilities are parsed successfully. In production, a warning would be logged.
462+
let mut data = BytesMut::new();
463+
464+
// Local address setup
465+
data.extend_from_slice(&[
466+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
467+
0x01, 0x01, // 192.168.1.1
468+
0x00, 0xB3, // local port 179
469+
0x00, 0xB3, // remote port 179
470+
]);
471+
472+
// Create BGP OPEN message WITHOUT multiprotocol capabilities (RFC 9069 violation)
473+
let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
474+
version: 4,
475+
asn: crate::models::Asn::new_32bit(65001),
476+
hold_time: 180,
477+
sender_ip: Ipv4Addr::new(192, 168, 1, 1),
478+
extended_length: false,
479+
opt_params: vec![], // No capabilities
480+
});
481+
let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
482+
data.extend_from_slice(&bgp_bytes);
483+
data.extend_from_slice(&bgp_bytes);
484+
485+
let afi = Afi::Ipv4;
486+
let asn_len = AsnLength::Bits32;
487+
let peer_type = BmpPeerType::LocalRib;
488+
489+
let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
490+
491+
assert!(result.is_ok(), "Parsing should succeed");
492+
// In production, a warning would be logged about missing multiprotocol capability
493+
}
494+
495+
#[test]
496+
fn test_local_rib_with_multiprotocol_capability() {
497+
// This test verifies that LocalRib peer up notifications WITH multiprotocol
498+
// capabilities are parsed successfully without warnings.
499+
let mut data = BytesMut::new();
500+
501+
// Local address setup
502+
data.extend_from_slice(&[
503+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
504+
0x01, 0x01, // 192.168.1.1
505+
0x00, 0xB3, // local port 179
506+
0x00, 0xB3, // remote port 179
507+
]);
508+
509+
// Create BGP OPEN message WITH multiprotocol capabilities (RFC 9069 compliant)
510+
let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
511+
version: 4,
512+
asn: crate::models::Asn::new_32bit(65001),
513+
hold_time: 180,
514+
sender_ip: Ipv4Addr::new(192, 168, 1, 1),
515+
extended_length: false,
516+
opt_params: vec![OptParam {
517+
param_type: 2, // capability
518+
param_len: 6,
519+
param_value: ParamValue::Capacities(vec![Capability {
520+
ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
521+
value: CapabilityValue::MultiprotocolExtensions(
522+
MultiprotocolExtensionsCapability {
523+
afi: Afi::Ipv4,
524+
safi: Safi::Unicast,
525+
},
526+
),
527+
}]),
528+
}],
529+
});
530+
let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
531+
data.extend_from_slice(&bgp_bytes);
532+
data.extend_from_slice(&bgp_bytes);
533+
534+
let afi = Afi::Ipv4;
535+
let asn_len = AsnLength::Bits32;
536+
let peer_type = BmpPeerType::LocalRib;
537+
538+
let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
539+
540+
assert!(result.is_ok(), "Parsing should succeed");
541+
// No warning should be logged when multiprotocol capability is present
542+
}
543+
544+
#[test]
545+
fn test_local_rib_without_vr_table_name_tlv() {
546+
// This test verifies that LocalRib peer up notifications without VrTableName TLV
547+
// are parsed successfully. In production, a warning would be logged.
548+
let mut data = BytesMut::new();
549+
550+
// Local address setup
551+
data.extend_from_slice(&[
552+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
553+
0x01, 0x01, // 192.168.1.1
554+
0x00, 0xB3, // local port 179
555+
0x00, 0xB3, // remote port 179
556+
]);
557+
558+
// Create BGP OPEN message with capabilities
559+
let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
560+
version: 4,
561+
asn: crate::models::Asn::new_32bit(65001),
562+
hold_time: 180,
563+
sender_ip: Ipv4Addr::new(192, 168, 1, 1),
564+
extended_length: false,
565+
opt_params: vec![OptParam {
566+
param_type: 2, // capability
567+
param_len: 6,
568+
param_value: ParamValue::Capacities(vec![Capability {
569+
ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
570+
value: CapabilityValue::MultiprotocolExtensions(
571+
MultiprotocolExtensionsCapability {
572+
afi: Afi::Ipv4,
573+
safi: Safi::Unicast,
574+
},
575+
),
576+
}]),
577+
}],
578+
});
579+
let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
580+
data.extend_from_slice(&bgp_bytes);
581+
data.extend_from_slice(&bgp_bytes);
582+
583+
// Add TLVs but NO VrTableName (RFC 9069 violation)
584+
data.extend_from_slice(&[0x00, 0x00]); // String TLV
585+
data.extend_from_slice(&[0x00, 0x04]); // length 4
586+
data.extend_from_slice(b"Test");
587+
588+
let afi = Afi::Ipv4;
589+
let asn_len = AsnLength::Bits32;
590+
let peer_type = BmpPeerType::LocalRib;
591+
592+
let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
593+
594+
assert!(result.is_ok(), "Parsing should succeed");
595+
// In production, a warning would be logged about missing VrTableName TLV
596+
}
597+
598+
#[test]
599+
fn test_local_rib_with_valid_vr_table_name_tlv() {
600+
// This test verifies that LocalRib peer up notifications with valid VrTableName TLV
601+
// are parsed successfully without warnings.
602+
let mut data = BytesMut::new();
603+
604+
// Local address setup
605+
data.extend_from_slice(&[
606+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
607+
0x01, 0x01, // 192.168.1.1
608+
0x00, 0xB3, // local port 179
609+
0x00, 0xB3, // remote port 179
610+
]);
611+
612+
// Create BGP OPEN message with capabilities
613+
let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
614+
version: 4,
615+
asn: crate::models::Asn::new_32bit(65001),
616+
hold_time: 180,
617+
sender_ip: Ipv4Addr::new(192, 168, 1, 1),
618+
extended_length: false,
619+
opt_params: vec![OptParam {
620+
param_type: 2, // capability
621+
param_len: 6,
622+
param_value: ParamValue::Capacities(vec![Capability {
623+
ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
624+
value: CapabilityValue::MultiprotocolExtensions(
625+
MultiprotocolExtensionsCapability {
626+
afi: Afi::Ipv4,
627+
safi: Safi::Unicast,
628+
},
629+
),
630+
}]),
631+
}],
632+
});
633+
let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
634+
data.extend_from_slice(&bgp_bytes);
635+
data.extend_from_slice(&bgp_bytes);
636+
637+
// Add VrTableName TLV with valid length (1-255 bytes)
638+
data.extend_from_slice(&[0x00, 0x03]); // VrTableName TLV type
639+
data.extend_from_slice(&[0x00, 0x08]); // length 8
640+
data.extend_from_slice(b"LocalRIB");
641+
642+
let afi = Afi::Ipv4;
643+
let asn_len = AsnLength::Bits32;
644+
let peer_type = BmpPeerType::LocalRib;
645+
646+
let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
647+
648+
assert!(result.is_ok(), "Parsing should succeed");
649+
650+
let peer_notification = result.unwrap();
651+
assert_eq!(peer_notification.tlvs.len(), 1);
652+
assert_eq!(peer_notification.tlvs[0].info_type, PeerUpTlvType::VrTableName);
653+
assert_eq!(peer_notification.tlvs[0].info_value, "LocalRIB");
654+
// No warnings should be logged with valid VrTableName
655+
}
656+
657+
#[test]
658+
fn test_local_rib_with_empty_vr_table_name() {
659+
// This test verifies that LocalRib peer up notifications with empty VrTableName
660+
// are parsed successfully. In production, a warning would be logged.
661+
let mut data = BytesMut::new();
662+
663+
// Local address setup
664+
data.extend_from_slice(&[
665+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
666+
0x01, 0x01, // 192.168.1.1
667+
0x00, 0xB3, // local port 179
668+
0x00, 0xB3, // remote port 179
669+
]);
670+
671+
// Create BGP OPEN message with capabilities
672+
let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
673+
version: 4,
674+
asn: crate::models::Asn::new_32bit(65001),
675+
hold_time: 180,
676+
sender_ip: Ipv4Addr::new(192, 168, 1, 1),
677+
extended_length: false,
678+
opt_params: vec![OptParam {
679+
param_type: 2, // capability
680+
param_len: 6,
681+
param_value: ParamValue::Capacities(vec![Capability {
682+
ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
683+
value: CapabilityValue::MultiprotocolExtensions(
684+
MultiprotocolExtensionsCapability {
685+
afi: Afi::Ipv4,
686+
safi: Safi::Unicast,
687+
},
688+
),
689+
}]),
690+
}],
691+
});
692+
let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
693+
data.extend_from_slice(&bgp_bytes);
694+
data.extend_from_slice(&bgp_bytes);
695+
696+
// Add VrTableName TLV with EMPTY value (RFC 9069 violation)
697+
data.extend_from_slice(&[0x00, 0x03]); // VrTableName TLV type
698+
data.extend_from_slice(&[0x00, 0x00]); // length 0 (empty)
699+
700+
let afi = Afi::Ipv4;
701+
let asn_len = AsnLength::Bits32;
702+
let peer_type = BmpPeerType::LocalRib;
703+
704+
let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
705+
706+
assert!(result.is_ok(), "Parsing should succeed");
707+
// In production, a warning would be logged about invalid VrTableName length
708+
}
709+
710+
#[test]
711+
fn test_local_rib_with_oversized_vr_table_name() {
712+
// This test verifies that LocalRib peer up notifications with oversized VrTableName
713+
// are parsed successfully. In production, a warning would be logged.
714+
let mut data = BytesMut::new();
715+
716+
// Local address setup
717+
data.extend_from_slice(&[
718+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
719+
0x01, 0x01, // 192.168.1.1
720+
0x00, 0xB3, // local port 179
721+
0x00, 0xB3, // remote port 179
722+
]);
723+
724+
// Create BGP OPEN message with capabilities
725+
let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
726+
version: 4,
727+
asn: crate::models::Asn::new_32bit(65001),
728+
hold_time: 180,
729+
sender_ip: Ipv4Addr::new(192, 168, 1, 1),
730+
extended_length: false,
731+
opt_params: vec![OptParam {
732+
param_type: 2, // capability
733+
param_len: 6,
734+
param_value: ParamValue::Capacities(vec![Capability {
735+
ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
736+
value: CapabilityValue::MultiprotocolExtensions(
737+
MultiprotocolExtensionsCapability {
738+
afi: Afi::Ipv4,
739+
safi: Safi::Unicast,
740+
},
741+
),
742+
}]),
743+
}],
744+
});
745+
let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
746+
data.extend_from_slice(&bgp_bytes);
747+
data.extend_from_slice(&bgp_bytes);
748+
749+
// Add VrTableName TLV with oversized value (>255 bytes, RFC 9069 violation)
750+
let oversized_name = "A".repeat(256);
751+
data.extend_from_slice(&[0x00, 0x03]); // VrTableName TLV type
752+
data.extend_from_slice(&[0x01, 0x00]); // length 256
753+
data.extend_from_slice(oversized_name.as_bytes());
754+
755+
let afi = Afi::Ipv4;
756+
let asn_len = AsnLength::Bits32;
757+
let peer_type = BmpPeerType::LocalRib;
758+
759+
let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
760+
761+
assert!(result.is_ok(), "Parsing should succeed");
762+
// In production, a warning would be logged about oversized VrTableName
763+
}
764+
765+
#[test]
766+
fn test_non_local_rib_no_validation() {
767+
// This test verifies that non-LocalRib peer types don't trigger LocalRib validations
768+
let mut data = BytesMut::new();
769+
770+
// Local address setup
771+
data.extend_from_slice(&[
772+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
773+
0x01, 0x01, // 192.168.1.1
774+
0x00, 0xB3, // local port 179
775+
0x00, 0xB3, // remote port 179
776+
]);
777+
778+
// Create BGP OPEN message WITHOUT capabilities (but not LocalRib, so no warning)
779+
let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
780+
version: 4,
781+
asn: crate::models::Asn::new_32bit(65001),
782+
hold_time: 180,
783+
sender_ip: Ipv4Addr::new(192, 168, 1, 1),
784+
extended_length: false,
785+
opt_params: vec![],
786+
});
787+
let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
788+
data.extend_from_slice(&bgp_bytes);
789+
data.extend_from_slice(&bgp_bytes);
790+
791+
let afi = Afi::Ipv4;
792+
let asn_len = AsnLength::Bits32;
793+
let peer_type = BmpPeerType::Global; // Not LocalRib
794+
795+
let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
796+
797+
assert!(result.is_ok(), "Parsing should succeed");
798+
// No warnings should be logged for non-LocalRib peer types
799+
}
451800
}

0 commit comments

Comments
 (0)