use super::event_forwarding::Reception;
use super::event_forwarding_tests::{
Copy, Forwarding, LOCAL_DEVICE, PEER_A, PEER_B, To, database, destination, notification,
unconfirmed,
};
use super::event_recipient_routing_tests::address_recipient;
use super::*;
use bacnet_objects::notification_forwarder::NotificationForwarderObject;
use bacnet_types::constructed::BACnetRecipient;
const REMOTE_MAC: [u8; 2] = [0x0C, 0x0D];
const BROADCAST: Reception = Reception {
group: true,
global: false,
};
fn confirmed(to: To, process_identifier: u32) -> Copy {
Copy {
to,
confirmed: true,
process_identifier,
}
}
#[tokio::test]
async fn a_destination_two_chained_forwarders_name_gets_one_copy() {
let local =
BACnetRecipient::Device(ObjectIdentifier::new(ObjectType::DEVICE, LOCAL_DEVICE).unwrap());
let mut a = NotificationForwarderObject::new(1, "A").unwrap();
a.set_process_identifier_filter(Some(1));
a.add_destination(destination(address_recipient(0, &PEER_A), 9, false))
.unwrap();
a.add_destination(destination(local, 2, false)).unwrap();
let mut b = NotificationForwarderObject::new(2, "B").unwrap();
b.set_process_identifier_filter(Some(2));
b.add_destination(destination(address_recipient(0, &PEER_A), 9, false))
.unwrap();
b.add_destination(destination(address_recipient(0, &PEER_B), 9, false))
.unwrap();
let forwarding = Forwarding::new(database(vec![a, b]));
assert_eq!(
forwarding
.receive(¬ification(1), Reception::UNICAST)
.await,
[
unconfirmed(To::Local(PEER_A.to_vec()), 9),
unconfirmed(To::Local(PEER_B.to_vec()), 9),
]
);
}
#[tokio::test]
async fn a_received_notification_no_forwarder_takes_is_counted() {
let mut only_seven = NotificationForwarderObject::new(1, "NF").unwrap();
only_seven.set_process_identifier_filter(Some(7));
only_seven
.add_destination(destination(address_recipient(0, &PEER_A), 40, false))
.unwrap();
let forwarding = Forwarding::new(database(vec![only_seven]));
assert!(
forwarding
.receive(¬ification(5), Reception::UNICAST)
.await
.is_empty()
);
assert_eq!(forwarding.counters().received_not_forwarded, 1);
assert_eq!(
forwarding
.receive(¬ification(7), Reception::UNICAST)
.await
.len(),
1
);
let global = Reception {
group: true,
global: true,
};
assert!(
forwarding
.receive(¬ification(5), global)
.await
.is_empty()
);
assert_eq!(
forwarding.counters(),
EventNotificationCounters {
received_not_forwarded: 1,
..Default::default()
}
);
}
#[tokio::test]
async fn a_copy_longer_than_the_local_apdu_capacity_is_dropped_and_counted() {
let mut nf = NotificationForwarderObject::new(1, "NF").unwrap();
nf.add_destination(destination(address_recipient(0, &PEER_A), 40, true))
.unwrap();
nf.add_destination(destination(address_recipient(0, &PEER_B), 41, false))
.unwrap();
let forwarding = Forwarding::new(database(vec![nf]));
let with_text = |length: usize| {
let mut request = notification(5);
request.message_text = Some("x".repeat(length));
request
};
let base = super::event_forwarding_tests::encoded(&with_text(300)).len();
let long = with_text(300 + 1473 - base);
assert_eq!(super::event_forwarding_tests::encoded(&long).len(), 1473);
assert_eq!(
forwarding.receive(&long, Reception::UNICAST).await,
[unconfirmed(To::Local(PEER_B.to_vec()), 41)]
);
assert_eq!(
forwarding.counters(),
EventNotificationCounters {
apdu_too_large: 1,
..Default::default()
}
);
}
#[tokio::test]
async fn a_bound_device_on_the_receiving_network_gets_no_copy_of_a_broadcast() {
let mut nf = NotificationForwarderObject::new(1, "NF").unwrap();
nf.add_destination(destination(
BACnetRecipient::Device(ObjectIdentifier::new(ObjectType::DEVICE, 60).unwrap()),
40,
false,
))
.unwrap();
let forwarding = Forwarding::new(database(vec![nf]));
forwarding.bind_device(60, &PEER_A).await;
assert_eq!(
forwarding
.receive(¬ification(5), Reception::UNICAST)
.await,
[unconfirmed(To::Local(PEER_A.to_vec()), 40)]
);
assert!(
forwarding
.receive(¬ification(5), BROADCAST)
.await
.is_empty()
);
}
#[tokio::test]
async fn a_broadcast_notification_goes_confirmed_only_off_the_receiving_network() {
let mut nf = NotificationForwarderObject::new(1, "NF").unwrap();
nf.add_destination(destination(address_recipient(0, &PEER_A), 40, true))
.unwrap();
nf.add_destination(destination(address_recipient(5, &REMOTE_MAC), 41, true))
.unwrap();
let forwarding = Forwarding::new(database(vec![nf]));
assert_eq!(
forwarding.receive(¬ification(5), BROADCAST).await,
[confirmed(To::Remote(5, REMOTE_MAC.to_vec()), 41)]
);
assert_eq!(forwarding.counters(), EventNotificationCounters::default());
}