use super::*;
use bacnet_types::constructed::{
BACnetAuthenticationPolicy, BACnetAuthenticationPolicyEntry, BACnetDeviceObjectReference,
};
fn oid(object_type: ObjectType, instance: u32) -> ObjectIdentifier {
ObjectIdentifier::new(object_type, instance).unwrap()
}
fn round_trip(policy: &BACnetAuthenticationPolicy, golden: &[u8]) {
let mut encoded = BytesMut::new();
encode_authentication_policy(&mut encoded, policy);
assert_eq!(&encoded[..], golden, "{policy:?}");
let (decoded, end) = decode_authentication_policy(golden, 0).unwrap();
assert_eq!(&decoded, policy);
assert_eq!(end, golden.len());
}
fn card_then_pin() -> BACnetAuthenticationPolicy {
BACnetAuthenticationPolicy {
policy: vec![
BACnetAuthenticationPolicyEntry {
credential_data_input: oid(ObjectType::CREDENTIAL_DATA_INPUT, 1).into(),
index: 1,
},
BACnetAuthenticationPolicyEntry {
credential_data_input: BACnetDeviceObjectReference {
device_identifier: Some(oid(ObjectType::DEVICE, 99)),
object_identifier: oid(ObjectType::CREDENTIAL_DATA_INPUT, 2),
},
index: 2,
},
],
order_enforced: true,
timeout: 30,
}
}
#[test]
fn authentication_policy_golden_bytes_and_round_trip() {
round_trip(
&card_then_pin(),
&[
0x0E, 0x0E, 0x1C, 0x09, 0x40, 0x00, 0x01, 0x0F, 0x19, 0x01, 0x0E, 0x0C, 0x02, 0x00, 0x00, 0x63, 0x1C, 0x09, 0x40, 0x00, 0x02, 0x0F, 0x19, 0x02, 0x0F, 0x19, 0x01, 0x29, 0x1E, ],
);
round_trip(
&BACnetAuthenticationPolicy::default(),
&[0x0E, 0x0F, 0x19, 0x00, 0x29, 0x00],
);
}
#[test]
fn authentication_policy_decoder_keeps_what_the_point_judges() {
let kept = BACnetAuthenticationPolicy {
policy: vec![
BACnetAuthenticationPolicyEntry {
credential_data_input: oid(ObjectType::ANALOG_INPUT, 1).into(),
index: 0,
},
BACnetAuthenticationPolicyEntry {
credential_data_input: oid(ObjectType::CREDENTIAL_DATA_INPUT, 1).into(),
index: u32::MAX,
},
],
order_enforced: false,
timeout: u32::MAX,
};
let mut encoded = BytesMut::new();
encode_authentication_policy(&mut encoded, &kept);
let (decoded, end) = decode_authentication_policy(&encoded, 0).unwrap();
assert_eq!(decoded, kept);
assert_eq!(end, encoded.len());
}
#[test]
fn authentication_policies_decode_one_element_at_a_time() {
let first = card_then_pin();
let second = BACnetAuthenticationPolicy::default();
let mut array = BytesMut::new();
encode_authentication_policy(&mut array, &first);
let boundary = array.len();
encode_authentication_policy(&mut array, &second);
let (decoded, end) = decode_authentication_policy(&array, 0).unwrap();
assert_eq!((decoded, end), (first, boundary));
let (decoded, end) = decode_authentication_policy(&array, boundary).unwrap();
assert_eq!((decoded, end), (second, array.len()));
}
#[test]
fn authentication_policy_rejects_malformed_elements() {
let malformed: [&[u8]; 11] = [
&[],
&[0x19, 0x00, 0x29, 0x00],
&[0x0E, 0x0E, 0x1C, 0x09, 0x40, 0x00, 0x01, 0x0F, 0x19, 0x01],
&[
0x0E, 0x1C, 0x09, 0x40, 0x00, 0x01, 0x19, 0x01, 0x0F, 0x19, 0x00, 0x29, 0x00,
],
&[
0x0E, 0x0E, 0x1C, 0x09, 0x40, 0x00, 0x01, 0x0F, 0x0F, 0x19, 0x00, 0x29, 0x00,
],
&[
0x0E, 0x0E, 0x1C, 0x09, 0x40, 0x00, 0x01, 0x1C, 0x09, 0x40, 0x00, 0x02, 0x0F, 0x19,
0x01, 0x0F, 0x19, 0x00, 0x29, 0x00,
],
&[
0x0E, 0x0E, 0x1C, 0x09, 0x40, 0x00, 0x01, 0x0F, 0x1D, 0x05, 0x01, 0x00, 0x00, 0x00,
0x00, 0x0F, 0x19, 0x00, 0x29, 0x00,
],
&[0x0E, 0x0F, 0x29, 0x00],
&[0x0E, 0x0F, 0x19, 0x02, 0x29, 0x00],
&[0x0E, 0x0F, 0x19, 0x00],
&[
0x0E, 0x0F, 0x19, 0x00, 0x2D, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
],
];
for octets in malformed {
assert!(
decode_authentication_policy(octets, 0).is_err(),
"{octets:02X?} decoded"
);
}
}