#![allow(clippy::unwrap_used, clippy::expect_used)]
use matter_clusters::gen;
use matter_clusters::types::Nullable;
use matter_codec::{Tag, TlvWriter};
fn uint_attr(v: u64) -> Vec<u8> {
let mut buf = Vec::new();
TlvWriter::new(&mut buf)
.put_uint(Tag::Anonymous, v)
.unwrap();
buf
}
fn int_attr(v: i64) -> Vec<u8> {
let mut buf = Vec::new();
TlvWriter::new(&mut buf).put_int(Tag::Anonymous, v).unwrap();
buf
}
fn bool_attr(v: bool) -> Vec<u8> {
let mut buf = Vec::new();
TlvWriter::new(&mut buf)
.put_bool(Tag::Anonymous, v)
.unwrap();
buf
}
fn null_attr() -> Vec<u8> {
let mut buf = Vec::new();
TlvWriter::new(&mut buf).put_null(Tag::Anonymous).unwrap();
buf
}
#[test]
fn illuminance_measured_value_decodes() {
assert_eq!(
gen::illuminance_measurement::decode_measured_value(&uint_attr(12345)).unwrap(),
Nullable::Value(12345)
);
assert_eq!(
gen::illuminance_measurement::decode_measured_value(&null_attr()).unwrap(),
Nullable::Null
);
}
#[test]
fn pressure_measured_value_decodes() {
assert_eq!(
gen::pressure_measurement::decode_measured_value(&int_attr(-50)).unwrap(),
Nullable::Value(-50)
);
}
#[test]
fn flow_measured_value_decodes() {
assert_eq!(
gen::flow_measurement::decode_measured_value(&uint_attr(200)).unwrap(),
Nullable::Value(200)
);
}
#[test]
fn boolean_state_state_value_decodes() {
assert!(gen::boolean_state::decode_state_value(&bool_attr(true)).unwrap());
}
#[test]
fn switch_current_position_decodes() {
assert_eq!(
gen::switch::decode_current_position(&uint_attr(2)).unwrap(),
2
);
}
fn uint_array_attr(values: &[u64]) -> Vec<u8> {
let mut buf = Vec::new();
{
let mut w = TlvWriter::new(&mut buf);
w.start_array(Tag::Anonymous).unwrap();
for &v in values {
w.put_uint(Tag::Anonymous, v).unwrap();
}
w.end_container().unwrap();
}
buf
}
#[test]
fn air_quality_decodes() {
use gen::air_quality::AirQualityEnum;
assert_eq!(
gen::air_quality::decode_air_quality(&uint_attr(1)).unwrap(),
AirQualityEnum::Good
);
assert_eq!(
gen::air_quality::decode_air_quality(&uint_attr(0)).unwrap(),
AirQualityEnum::Unknown
);
assert_eq!(
gen::air_quality::decode_air_quality(&uint_attr(99)).unwrap(),
AirQualityEnum::Unrecognized(99)
);
}
#[test]
fn power_source_status_and_lists_decode() {
use gen::power_source::{PowerSourceStatusEnum, WiredFaultEnum};
assert_eq!(
gen::power_source::decode_status(&uint_attr(1)).unwrap(),
PowerSourceStatusEnum::Active
);
assert_eq!(
gen::power_source::decode_active_wired_faults(&uint_array_attr(&[1])).unwrap(),
vec![WiredFaultEnum::OverVoltage]
);
assert_eq!(
gen::power_source::decode_endpoint_list(&uint_array_attr(&[1, 2])).unwrap(),
vec![1u16, 2u16]
);
}
#[test]
fn electrical_power_measurement_decodes() {
use gen::electrical_power_measurement as epm;
assert_eq!(
epm::decode_power_mode(&uint_attr(2)).unwrap(),
epm::PowerModeEnum::Ac
);
assert_eq!(
epm::decode_voltage(&int_attr(230_000)).unwrap(),
Nullable::Value(230_000)
);
assert!(epm::decode_accuracy(&uint_array_attr(&[]))
.unwrap()
.is_empty());
assert!(matches!(
epm::decode_harmonic_currents(&null_attr()).unwrap(),
Nullable::Null
));
}
#[test]
fn electrical_energy_measurement_nullable_struct_attr_decodes() {
assert!(matches!(
gen::electrical_energy_measurement::decode_cumulative_energy_imported(&null_attr())
.unwrap(),
Nullable::Null
));
}
#[test]
fn thermostat_system_mode_decodes() {
use gen::thermostat::SystemModeEnum;
assert_eq!(
gen::thermostat::decode_system_mode(&uint_attr(4)).unwrap(),
SystemModeEnum::Heat
);
}
#[test]
fn thermostat_atomic_response_decodes_synth_struct() {
use matter_codec::{ContainerKind, Element, TlvReader};
let mut buf = Vec::new();
{
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous).unwrap();
w.put_uint(Tag::Context(0), 0).unwrap();
w.start_array(Tag::Context(1)).unwrap();
w.start_structure(Tag::Anonymous).unwrap();
w.put_uint(Tag::Context(0), 0x1234).unwrap();
w.put_uint(Tag::Context(1), 0).unwrap();
w.end_container().unwrap();
w.end_container().unwrap();
w.put_uint(Tag::Context(2), 1000).unwrap();
w.end_container().unwrap();
}
let mut r = TlvReader::new(&buf);
assert!(matches!(
r.next().unwrap(),
Some(Element::ContainerStart {
kind: ContainerKind::Structure,
..
})
));
let resp = gen::thermostat::AtomicResponse::decode_from(&mut r).unwrap();
assert_eq!(resp.status_code, 0);
assert_eq!(resp.attribute_status.len(), 1);
assert_eq!(resp.attribute_status[0].attribute_id, 0x1234);
assert_eq!(resp.attribute_status[0].status_code, 0);
assert_eq!(resp.timeout, Some(1000));
}
#[test]
fn fan_control_fan_mode_decodes() {
use gen::fan_control::FanModeEnum;
assert_eq!(
gen::fan_control::decode_fan_mode(&uint_attr(3)).unwrap(),
FanModeEnum::High
);
}
#[test]
fn tuic_keypad_lockout_decodes() {
use gen::thermostat_user_interface_configuration::KeypadLockoutEnum;
assert_eq!(
gen::thermostat_user_interface_configuration::decode_keypad_lockout(&uint_attr(0)).unwrap(),
KeypadLockoutEnum::NoLockout
);
}
#[test]
fn pump_operation_mode_decodes() {
use gen::pump_configuration_and_control::OperationModeEnum;
assert_eq!(
gen::pump_configuration_and_control::decode_operation_mode(&uint_attr(0)).unwrap(),
OperationModeEnum::Normal
);
}
#[test]
fn window_covering_mode_decodes() {
let m = gen::window_covering::decode_mode(&uint_attr(1)).unwrap();
assert_eq!(m.bits(), 1);
}
#[test]
fn binding_target_struct_decodes_fabric_index() {
use matter_codec::{ContainerKind, Element, TlvReader};
let mut buf = Vec::new();
{
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous).unwrap();
w.put_uint(Tag::Context(4), 0x0006).unwrap();
w.put_uint(Tag::Context(254), 1).unwrap();
w.end_container().unwrap();
}
let mut r = TlvReader::new(&buf);
assert!(matches!(
r.next().unwrap(),
Some(Element::ContainerStart {
kind: ContainerKind::Structure,
..
})
));
let t = gen::binding::TargetStruct::decode_from(&mut r).unwrap();
assert_eq!(t.cluster, Some(0x0006));
assert_eq!(t.fabric_index, 1u8);
}
#[test]
fn fixed_label_label_struct_decodes() {
use matter_codec::{ContainerKind, Element, TlvReader};
let mut buf = Vec::new();
{
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous).unwrap();
w.put_utf8(Tag::Context(0), "room").unwrap();
w.put_utf8(Tag::Context(1), "kitchen").unwrap();
w.end_container().unwrap();
}
let mut r = TlvReader::new(&buf);
assert!(matches!(
r.next().unwrap(),
Some(Element::ContainerStart {
kind: ContainerKind::Structure,
..
})
));
let l = gen::fixed_label::LabelStruct::decode_from(&mut r).unwrap();
assert_eq!(l.label, "room");
assert_eq!(l.value, "kitchen");
}
#[test]
fn groups_add_group_command_encodes_wellformed() {
use matter_codec::{Element, TlvReader, Value};
let bytes = gen::groups::encode_add_group(0x0007, &"den".to_string());
let mut r = TlvReader::new(&bytes);
assert!(matches!(
r.next().unwrap(),
Some(Element::ContainerStart { .. })
));
assert!(matches!(
r.next().unwrap(),
Some(Element::Scalar {
tag: Tag::Context(0),
value: Value::Uint(7)
})
));
assert!(matches!(
r.next().unwrap(),
Some(Element::Scalar { tag: Tag::Context(1), value: Value::Utf8(ref s) }) if s == "den"
));
}
#[test]
fn groups_get_group_membership_command_encodes_list() {
use matter_codec::{ContainerKind, Element, TlvReader, Value};
let bytes = gen::groups::encode_get_group_membership(&vec![1u16, 2u16]);
let mut r = TlvReader::new(&bytes);
assert!(matches!(
r.next().unwrap(),
Some(Element::ContainerStart { .. })
));
assert!(matches!(
r.next().unwrap(),
Some(Element::ContainerStart {
tag: Tag::Context(0),
kind: ContainerKind::Array
})
));
assert!(matches!(
r.next().unwrap(),
Some(Element::Scalar {
value: Value::Uint(1),
..
})
));
assert!(matches!(
r.next().unwrap(),
Some(Element::Scalar {
value: Value::Uint(2),
..
})
));
}
#[test]
fn access_control_entry_decodes_subjects_u64() {
use matter_codec::{ContainerKind, Element, TlvReader};
let mut buf = Vec::new();
{
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous).unwrap();
w.put_uint(Tag::Context(1), 5).unwrap();
w.put_uint(Tag::Context(2), 2).unwrap();
w.start_array(Tag::Context(3)).unwrap();
w.put_uint(Tag::Anonymous, 0x1122_3344_5566_7788).unwrap();
w.end_container().unwrap();
w.put_null(Tag::Context(4)).unwrap();
w.put_uint(Tag::Context(254), 1).unwrap();
w.end_container().unwrap();
}
let mut r = TlvReader::new(&buf);
assert!(matches!(
r.next().unwrap(),
Some(Element::ContainerStart {
kind: ContainerKind::Structure,
..
})
));
let e = gen::access_control::AccessControlEntryStruct::decode_from(&mut r).unwrap();
assert_eq!(e.subjects, Nullable::Value(vec![0x1122_3344_5566_7788u64]));
assert!(matches!(e.targets, Nullable::Null));
assert_eq!(e.fabric_index, 1u8);
}
#[test]
fn group_key_set_write_encodes_wellformed() {
use matter_codec::{Element, TlvReader};
let gks = gen::group_key_management::GroupKeySetStruct {
group_key_set_id: 0x0042,
group_key_security_policy: gen::group_key_management::GroupKeySecurityPolicyEnum::from_raw(
0,
),
epoch_key0: Nullable::Value(vec![0xab; 16]),
epoch_start_time0: Nullable::Value(1234),
epoch_key1: Nullable::Null,
epoch_start_time1: Nullable::Null,
epoch_key2: Nullable::Null,
epoch_start_time2: Nullable::Null,
group_key_multicast_policy: None,
fabric_index: None,
};
let bytes = gen::group_key_management::encode_key_set_write(gks);
let mut r = TlvReader::new(&bytes);
assert!(matches!(
r.next().unwrap(),
Some(Element::ContainerStart { .. })
));
assert!(matches!(
r.next().unwrap(),
Some(Element::ContainerStart {
tag: Tag::Context(0),
..
})
));
}
#[test]
fn admin_open_basic_commissioning_window_encodes() {
use matter_codec::{Element, TlvReader, Value};
let bytes = gen::administrator_commissioning::encode_open_basic_commissioning_window(180);
let mut r = TlvReader::new(&bytes);
assert!(matches!(
r.next().unwrap(),
Some(Element::ContainerStart { .. })
));
assert!(matches!(
r.next().unwrap(),
Some(Element::Scalar {
tag: Tag::Context(0),
value: Value::Uint(180)
})
));
}
#[test]
fn ota_announce_provider_encodes_scalars_and_enum() {
use gen::ota_software_update_requestor::AnnouncementReasonEnum;
use matter_codec::{Element, TlvReader, Value};
let bytes = gen::ota_software_update_requestor::encode_announce_ota_provider(
0x0000_0000_0000_1234,
0xFFF1,
AnnouncementReasonEnum::SimpleAnnouncement,
None,
1,
);
let mut r = TlvReader::new(&bytes);
assert!(matches!(
r.next().unwrap(),
Some(Element::ContainerStart { .. })
));
assert!(matches!(
r.next().unwrap(),
Some(Element::Scalar {
tag: Tag::Context(0),
value: Value::Uint(0x1234)
})
));
}
#[test]
fn ota_provider_query_image_encodes_scalars() {
use gen::ota_software_update_provider::{encode_query_image, DownloadProtocolEnum};
use matter_codec::{Element, TlvReader, Value};
let bytes = encode_query_image(
0xFFF1,
0x8000,
5,
&vec![DownloadProtocolEnum::BdxSynchronous],
None,
None,
None,
None,
);
let mut r = TlvReader::new(&bytes);
assert!(matches!(
r.next().unwrap(),
Some(Element::ContainerStart { .. })
));
assert!(matches!(
r.next().unwrap(),
Some(Element::Scalar {
tag: Tag::Context(0),
value: Value::Uint(0xFFF1)
})
));
}
#[test]
fn ota_provider_query_image_response_decodes() {
use gen::ota_software_update_provider::{QueryImageResponse, StatusEnum};
use matter_codec::{Element, Tag, TlvReader, TlvWriter};
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous).unwrap();
w.put_uint(Tag::Context(0), 0).unwrap(); w.end_container().unwrap();
let mut r = TlvReader::new(&buf);
assert!(matches!(
r.next().unwrap(),
Some(Element::ContainerStart { .. })
));
let decoded = QueryImageResponse::decode_from(&mut r).expect("decode QueryImageResponse");
assert_eq!(decoded.status, StatusEnum::UpdateAvailable);
}
#[test]
fn time_sync_utc_time_and_granularity_decode() {
use gen::time_synchronization::{decode_granularity, decode_utc_time, GranularityEnum};
let decoded = decode_utc_time(&uint_attr(780_000_000_000_000)).unwrap();
assert_eq!(decoded, Nullable::Value(780_000_000_000_000));
let g = decode_granularity(&uint_attr(2)).unwrap();
assert_eq!(g, GranularityEnum::SecondsGranularity);
}
#[test]
fn icd_register_client_response_and_operating_mode_decode() {
use gen::icd_management::{decode_operating_mode, OperatingModeEnum, RegisterClientResponse};
use matter_codec::{Tag, TlvWriter};
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous).unwrap();
w.put_uint(Tag::Context(0), 7).unwrap();
w.end_container().unwrap();
let decoded = RegisterClientResponse::decode(&buf).expect("decode RegisterClientResponse");
assert_eq!(decoded.icd_counter, 7);
let m = decode_operating_mode(&uint_attr(1)).unwrap();
assert_eq!(m, OperatingModeEnum::Lit);
}
#[test]
fn time_sync_set_time_zone_response_decodes() {
use gen::time_synchronization::SetTimeZoneResponse;
use matter_codec::{Tag, TlvWriter};
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous).unwrap();
w.put_bool(Tag::Context(0), true).unwrap();
w.end_container().unwrap();
let decoded = SetTimeZoneResponse::decode(&buf).expect("decode SetTimeZoneResponse");
assert!(decoded.dst_offset_required);
}